RabbitMQ说明与安装

一、RabbitMQ介绍
1. RabbitMQ 的相关概念
2007 年发布,是一个在 AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。
RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue 高级消息队列协议 )的开源实现,由于erlang 语言的高并发特性,性能较好,本质是个队列,FIFO 先入先出,里面存放的内容是message
RabbitMQ 是一个消息中间件:它接收消息并且转发,就类似于一个快递站,卖家把快递通过快递站,送到我们的手上,MQ也是这样,接收并存储消息,再转发。


2. 为什么要用 MQ
流量消峰
举个例子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这时有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。
简单来说: 就是在访问量剧增的情况下,但是应用仍然不能停,比如“双十一”下单的人多,但是淘宝这个应用仍然要运行,所以就可以使用消息中间件采用队列的形式减少突然访问的压力

应用解耦
以电商应用为例,应用中有订单系统、库存系统、物流系统、支付系统。用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流系统恢复后,继续处理订单信息即可,中间用户感受不到物流系统的故障,提升系统的可用性。

如图:
把支付,库存,物流都交给MQ



异步处理
有些服务间调用是异步的,例如 A 调用 B,B 需要花费很长时间执行,但是 A 需要知道 B 什么时候可以执行完,以前一般有两种方式,A 过一段时间去调用 B 的查询 api 查询。或者 A 提供一个 callback api, B 执行完之后调用 api 通知 A 服务。
这两种方式都不是很优雅,使用消息总线,可以很方便解决这个问题,A 调用 B 服务后,只需要监听 B 处理完成的消息,当 B 处理完成后,会发送一条消息给 MQ,MQ 会将此消息转发给 A 服务。这样 A 服务既不用循环调用 B 的查询 api,也不用提供 callback api。同样 B 服务也不用做这些操作。A 服务还能及时的得到异步处理成功的消息。

 
3. 四大核心概念
生产者:
产生数据发送消息的程序是生产者

交换机
交换机是RabbitMQ非常重要的一个部件,一方面它接收来自生产者的消息,另一方面它将消息推送到队列中。交换机必须确切知道如何处理它接收到的消息,是将这些消息推送到特定队列还是推送到多个队列,亦或者是把消息丢弃,这个得有交换机类型决定

队列
队列是 RabbitMQ 内部使用的一种数据结构,尽管消息流经 RabbitMQ 和应用程序,但它们只能存储在队列中。队列仅受主机的内存和磁盘限制的约束,本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,许多消费者可以尝试从一个队列接收数据。这就是我们使用队列的方式

消费者
消费与接收具有相似的含义。消费者大多时候是一个等待接收消息的程序。请注意生产者,消费者和消息中间件很多时候并不在同一机器上。同一个应用程序既可以是生产者又是可以是消费者。



4. RabbitMQ 核心部分
    Hello Wold 简单模式
    Work queues工作 队列模式
    Publish/Subscribe发布订阅模式
    Routing 路由模式
    Topics 主题模式
    Publisher Confirms 发布确认模式


5. RabbitMQ工作原理

 

 

Broker:接收和分发消息的应用,RabbitMQ Server 就是 Message Broker

Virtual host:出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念。当多个不同的用户使用同一个RabbitMQ server 提供的服务时,可以划分出多个 vhost,每个用户在自己的 vhost 创建 exchange/queue 等

Connection:publisher/consumer 和 broker 之间的 TCP 连接

Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection 的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个 thread 创建单独的 channel 进行通讯,AMQP method 包含了 channel id 帮助客户端和 message broker 识channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的Connection 极大减少了操作系统建立 TCP connection 的开销

Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到 queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)

Queue:消息最终被送到这里等待 consumer 取走

Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key,Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据



工作原理
生产者发送消息到 broker server(RabbitMQ),在 Broker 内部,用户创建Exchange/Queue,通过 Binding 规则将两者联系在一起,Exchange 分发消息,根据类型/binding 的不同分发策略有区别,消息最后来到 Queue 中,等待消费者取走。

 

二、RabbitMQ 单机部署

RabbitMQ是一个开源的遵循AMQP协议实现的基于Erlang语言编写,**即需要先安装部署Erlang环境再安装RabbitMQ环境。两者版本号的对应表(https://www.rabbitmq.com/which-erlang.html),安装相应版本的Erlang和RabbitMQ,只需在下文修改命令里面的版本号即可。

[root@localhost7h ~]# wget --content-disposition https://packagecloud.io/rabbitmq/erlang/packages/el/7/erlang-22.3.4.12-1.el7.x86_64.rpm/download.rpm
[root@localhost7h ~]# wget  https://packagecloud.io/rabbitmq/rabbitmq-server/packages/el/7/rabbitmq-server-3.7.22-1.el7.noarch.rpm

# Key 导入(可选)
[root@localhost7h ~]# rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc

#安装
[root@localhost7h ~]# yum install erlang-22.3.4.12-1.el7.x86_64.rpm 
[root@localhost7h ~]# yum install rabbitmq-server-3.7.22-1.el7.noarch.rpm

#启动
systemctl start rabbitmq-server.service


#RabbitMQ 插件管理: 
    5672:消费者访问的 端口
    15672:web 管理端口
    25672:集群状态通信端口

#开启 web 界面管理插件
[root@localhost7h ~]# rabbitmq-plugins  list
[root@localhost7h ~]# rabbitmq-plugins enable rabbitmq_management



默认禁止使用guest登陆 web 管理界面: 
rabbitmq 从 3.3.0 开始禁止使用 guest/guest 权限通过除 localhost 外的访问,
[root@localhost7h ~]#vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.3.3/ebin/rabbit.app
39 {loopback_users, []}, #删除被禁止登陆的 guest 账户

[root@localhost7h ~]# systemctl restart rabbitmq-server.service #重启 rabbitmq 服务




#添加用户,默认的virtual hosts 是 /
[root@localhost7h ~]# rabbitmqctl  add_user jack  123456

#设置用户分配操作权限。
[root@localhost7h ~]# rabbitmqctl  set_user_tags jack administrator

#设置对”virtual hosts 是 /“的权限。
[root@localhost7h ~]# rabbitmqctl  set_permissions  jack  ".*" ".*" ".*" 

三、RabbitMQ 集群部署

 

Rabbitmq 集群分为二种方式:
普通模式:创建好 RabbitMQ 集群之后的默认模式。
镜像模式:把需要的队列做成镜像队列。

普通集群模式:queue 创建之后,如果没有其它 policy,消息实体只存在于其中
一个节点,A、B 两个 Rabbitmq 节点仅有相同的元数据,即队列结构,但队列的
数据仅保存有一份,即创建该队列的 rabbitmq 节点(A 节点),当消息进入 A 节
点的 Queue 中后,consumer 从 B 节点拉取时,RabbitMQ 会临时在 A、B 间进行
消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer,所以 consumer 可
以连接每一个节点,从中取消息,该模式存在一个问题就是当 A 节点故障后,B
节点无法取到 A 节点中还未消费的消息实体。



镜像集群模式:
把需要的队列做成镜像队列,存在于多个节点,属于 RabbitMQ 的 HA 方案(镜
像模式是在普通模式的基础上,增加一些镜像策略)
该模式解决了普通模式中的数据丢失问题,其实质和普通模式不同之处在于,消
息实体会主动在镜像节点间同步,而不是在 consumer 取数据时临时拉取,该模
式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之
大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在
对可靠性要求较高的场合中适用,一个队列想做成镜像队列,需要先设置 policy,
然后客户端创建队列的时候,rabbitmq 集群根据“队列名称”自动设置是普通集
群模式或镜像队列。



集群中有两种节点类型:
内存节点:只将数据保存到内存
磁盘节点:保存数据到内存和磁盘。
内存节点虽然不写入磁盘,但是它执行比磁盘节点要好,集群中,只需要一个磁盘节点来保存数据就足够了如果集群中只有内存节点,那么不能全部停止它们,否则所有数据消息在服务器全部停机之后都会丢失。



推荐设计架构:
在一个 rabbitmq 集群里,有 3 台或以上机器,其中 1 台使用磁盘模式,其它节点使用内存模式,内存节点无访问速度更快,由于磁盘 IO 相对较慢,因此可作为数据备份使用。

后期rabbitmq,千万不要改主机名.

  集群状态监控:API接口:

  [root@localhost7J local]# curl -s -u guest:guest http://192.168.80.170:15672/api/nodes


1.主机名解析配置
[root@localhost7h local]# cat  /etc/hosts
192.168.80.170  localhost7H.localdomain
192.168.80.180  localhost7I.localdomain
192.168.80.190  localhost7J.localdomain


2.安装软件
[root@localhost7# yum install erlang-22.3.4.12-1.el7.x86_64.rpm 
[root@localhost7# yum install rabbitmq-server-3.7.22-1.el7.noarch.rpm



3.同步 RabbitMQ 集群的cookie文件: 
Rabbitmq 的集群是依赖于 erlang 的集群来工作的,所以必须先构建起 erlang 的集群环境,而 Erlang 的集群中各节点是通过一个 magic cookie 来实现的,这个
cookie 存放在 /var/lib/rabbitmq/.erlang.cookie 中,文件是 400 的权限,所以必须保证各节点 cookie 保持一致,否则节点之间就无法通信。

[root@localhost7h ~]#scp  /var/lib/rabbitmq/.erlang.cookie  192.168.80.180:/var/lib/rabbitmq/.erlang.cookie
[root@localhost7h ~]#scp  /var/lib/rabbitmq/.erlang.cookie  192.168.80.190:/var/lib/rabbitmq/.erlang.cookie

设置文件权限属性(三台都设置)
[root@localhost7J local]# chown  rabbitmq:rabbitmq  /var/lib/rabbitmq/.erlang.cookie



创建 RabbitMQ 集群:
在localhost7h 作为内存节点添加到 localhost7J,并作为内存节点(默认为磁盘节点),在localhost7h操作
[root@localhost7h ~]#rabbitmqctl stop_app  #停止 app 服务
[root@localhost7h ~]#rabbitmqctl reset     #清空元数据
[root@localhost7h ~]#rabbitmqctl join_cluster rabbit@localhost7J --ram  #注意:我用了短域名。
[root@localhost7h ~]#rabbitmqctl join_cluster rabbit@localhost7J.localdomain --ram  #失败。

[root@localhost7i ~]#rabbitmqctl stop_app 
[root@localhost7i ~]#rabbitmqctl reset
[root@localhost7i ~]#rabbitmqctl join_cluster rabbit@localhost7J --ram



查看当前集群状态
[root@localhost7h local]# rabbitmqctl cluster_status
Cluster status of node rabbit@localhost7h ...
[{nodes,[{disc,[rabbit@localhost7J]},   #磁盘节点,集群中至少有一个节点是磁盘节点用于数据持久化
         {ram,[rabbit@localhost7h,rabbit@localhost7I]}]}, #内存节点
 {running_nodes,[rabbit@localhost7I,rabbit@localhost7J,rabbit@localhost7h]},  # 节点
 {cluster_name,<<"rabbit@localhost7h.localdomain">>}, #  #当前正在运行的节点.
 {partitions,[]},
 {alarms,[{rabbit@localhost7I,[]},
          {rabbit@localhost7J,[]},
          {rabbit@localhost7h,[]}]}]



其它命令说明:
#添加用户,默认的virtual hosts 是 /
[root@localhost7h ~]# rabbitmqctl  add_user jack  123456

#创建 vhost
[root@localhost7J local]# rabbitmqctl add_vhost  zzhz
Adding vhost "zzhz" ...

#列出所有 vhost
[root@localhost7J local]# rabbitmqctl list_vhosts
Listing vhosts ...
name
/
magedu
zzhz

#列出所有队列
[root@localhost7J local]# rabbitmqctl list_queues 
Timeout: 60.0 seconds ...
Listing queues for vhost / ...

#删除指定 vhost
root@mq-server1:~#
[root@localhost7J local]# rabbitmqctl delete_vhost  magedu
Deleting vhost "magedu" ...


#设置 jack 用户对 zzhz 的 vhost 有读写权限,三个点为配置正则、读和写
[root@localhost7J local]# rabbitmqctl set_permissions -p zzhz jack ".*" "" ""
Setting permissions for user "jack" in vhost "zzhz" ...

#设置镜像策略
[root@localhost7J local]# rabbitmqctl list_policies
Listing policies for vhost "/" ...

[root@localhost7J local]# rabbitmqctl set_policy ha-all "#" '{"ha-mode":"all"}'
Setting policy "ha-all" for pattern "#" to "{"ha-mode":"all"}" with priority "0" for vhost "/" ...
[root@localhost7J local]#
[root@localhost7J local]#
[root@localhost7J local]#
[root@localhost7J local]# rabbitmqctl list_policies
Listing policies for vhost "/" ...
vhost name pattern apply-to definition priority
/ ha-all # all {"ha-mode":"all"} 0

 

 

 

 

posted @ 2023-01-16 15:06  yuanbangchen  阅读(65)  评论(0编辑  收藏  举报