文章目录
  1. 1. RabbiMQ简介
  2. 2. RabbiMQ模式
  3. 3. RabbiMQ特点
  4. 4. 搭建环境:
  5. 5. 搭建步骤
    1. 5.1. 1. 配置hosts文件
    2. 5.2. 2.安装erlang和rabbitmq-server软件
    3. 5.3. 3.修改rabbitmq config配置
    4. 5.4. 4. 安装管理插件
    5. 5.5. 5. 调整最大可打开文件句柄限制
    6. 5.6. 6.拷贝erlang.cookie
    7. 5.7. 7.将mq02、mq03作为内存节点加入mq01节点集群中
    8. 5.8. 8.查看集群状态
    9. 5.9. 9.RabbitMQ镜像集群配置
    10. 5.10. 10.其他功能指令使用
    11. 5.11. 11.rabbitmq网络分区配置-脑裂详解

RabbiMQ简介

RabbiMQ是用Erang开发的,集群非常方便,因为Erlang天生就是一门分布式语言,但其本身并不支持负载均衡。

RabbiMQ模式

RabbitMQ模式大概分为以下三种:
(1)单一模式。
(2)普通模式(默认的集群模式)。
(3) 镜像模式(把需要的队列做成镜像队列,存在于多个节点,属于RabbiMQ的HA方案,在对业务可靠性要求较高的场合中比较适用)。
要实现镜像模式,需要先搭建一个普通集群模式,在这个模式的基础上再配置镜像模式以实现高可用。

RabbiMQ特点

RabbitMQ的集群节点包括内存节点、磁盘节点。RabbitMQ支持消息的持久化
也就是数据写在磁盘上,最合适的方案就是既有内存节点,又有磁盘节点。

搭建环境:

IP地址 主机名 操作系统 防火墙和SELinux 用途
192.168.100.143 mq01 CentOS7.4(64位) 关闭 磁盘节点
192.168.100.144 mq02 CentOS7.4(64位) 关闭 内存节点
192.168.100.145 mq03 CentOS7.4(64位) 关闭 内存节点

注意:RabbitMQ集群节点必须在同一网段里,如果是跨广域网,效果会变差。

搭建步骤

1. 配置hosts文件

更改三台MQ节点的计算机名分别为mq01、mq02 和mq03,然后修改hosts配置文件

1
2
3
4
5
6
7
vi /etc/hostname    //其他两台相同,mq02,mq03
mq01

vi /etc/hosts
192.168.100.143 mq01 //注意不能带.注意-主机名称也要更改
192.168.100.144 mq02
192.168.100.145 mq03

注意:当主机名称不方便改动的情况,只修改hosts,同主机名就行

2.安装erlang和rabbitmq-server软件

在各个服务器上先安装好单机的rabbitmq,并能够成功启动,官方安装说明地址:https://www.rabbitmq.com/install-rpm.html#managing-service, 参考文件,选择合适的erlang和rabbitmq对应版本下载安装

由于服务器不可访问外网,所以本次通过官网下好rpm包,上传到服务器,再通过yum install安装
本次下载安装的版本为:
erlang-21.3.8.14-1.el7.x86_64.rpm 下载地址(https://bintray.com/rabbitmq-erlang/rpm/erlang)
rabbitmq-server-3.8.3-1.el7.noarch.rpm 下载地址(https://bintray.com/rabbitmq/rpm/rabbitmq-server)

根据系统CentOS的版本(6.x,7.x,8.x)选择合适的版本(el6,el7,el8)下载

分别使用如下命令安装

1
2
yum install -y erlang-21.3.8.14-1.el7.x86_64.rpm
yum install -y rabbitmq-server-3.8.3-1.el7.noarch.rpm

3.修改rabbitmq config配置

上一步安装完成,便可以通过systemctl start rabbitmq-server启动rabbitmq服务,通过启动日记,可以发现其未找到config文件,以及数据路径和日记路径都采用默认,这里我们做下调整优化,可以让rabbitmq使用更大上限的File descriptor,Disk space等
rabbitmq默认的加载配置文件在/etc/rabbitmq路径下,在此路径下新建rabbitmq-env.conf文件,来指明数据和日记存储的磁盘路径,内容如下:

1
2
MNESIA_BASE=/data/rabbitmq/data
LOG_BASE=/data/rabbitmq/log

通过df -h查看发现挂载的/data下有很大磁盘空间,遂放置于此。同时注意新建的/data/rabbitmq文件拥有设置为rabbitmq
使用命令:
chown -R rabbitmq:rabbitmq /data/rabbitmq/

再新建rabbitmq.conf文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
listeners.tcp.default = 5672

channel_max = 655360
# partition config
cluster_partition_handling = autoheal

# DANGER ZONE!
# allowing remote connections for default user is highly discouraged
# as it dramatically decreases the security of the system. Delete the user
# instead and create a new one with generated secure credentials.
loopback_users = none

此处优化了channel_max的上限,cluster_partition_handling为网络分区策略设置为autoheal,参见文章最后,rabbitMq脑裂详解。配置loopback_users=none,使得默认账户guest/guest可以在非localhost的情况下登陆访问rabbitmq管理界面。

以上优化参数的配置,在官方文档中均有说明,同时提供example配置文件供参考

4. 安装管理插件

RabbitMQ提供了一个非常友好的图形化监控页面插件(rabbitmq_management),让我们可以一目了然看见Rabbit的状态或集群状态。

1
2
3
4
5
/usr/lib/rabbitmq/bin/rabbitmq-plugins list //查看插件安装情况

/usr/lib/rabbitmq/bin/rabbitmq-plugins enable rabbitmq_management //启用rabbitmq_management服务

systemctl restart rabbitmq-server

5. 调整最大可打开文件句柄限制

默认情况下,操作系统限制的rabbitmq的最大操作文件句柄256,往往会限制到rabiitmq的性能提升,这里需要调整到65536

打开rabbitmq-server文件,位于系统:/usr/lib/systemd/system/rabbitmq-server.service,可通过systemctl status rabbitmq-server查看到,修改如下:

1
2
[Service]
LimitNOFILE=65536

以上完成单一mq的服务部署,在三台服务器完成相同的部署操作,并能够成功启动,登陆访问管理界面。
Rabbitmq的集群是依附于erlang的集群来工作的,所以必须先构建起erlang的集群景象。Erlang的集群中各节点是经由过程一个magic cookie来实现的,这个cookie存放在/var/lib/rabbitmq/.erlang.cookie中,文件是400的权限。所以必须保证各节点cookie一致,不然节点之间就无法通信。
用scp的方式将mq01节点的.erlang.cookie的值复制到其他两个节点中。

1
2
3
scp /var/lib/rabbitmq/.erlang.cookie root@192.168.100.144:/var/lib/rabbitmq/.erlang.cookie

scp /var/lib/rabbitmq/.erlang.cookie root@192.168.100.145:/var/lib/rabbitmq/.erlang.cookie

拷贝过程以及拷贝后注意文件权限问题。并重启三个服务应用。

7.将mq02、mq03作为内存节点加入mq01节点集群中

在mq02、mq03执行如下命令:

1
2
3
rabbitmqctl stop_app    //停掉rabbit应用
rabbitmqctl join_cluster --ram rabbit@mq01 //加入到磁盘节点
rabbitmqctl start_app //启动rabbit应用

(1)默认rabbitmq启动后是磁盘节点,在这个cluster命令下,mq02和mq03是内存节点,mq01是磁盘节点。
(2)如果要使mq02、mq03都是磁盘节点,去掉–ram参数即可。
(3)如果想要更改节点类型,可以使用命令rabbitmqctl change_cluster_node_type disc(ram),前提是必须停掉rabbit应用

在RabbitMQ集群集群中,必须至少有一个磁盘节点,否则队列元数据无法写入到集群中,当磁盘节点宕掉时,集群将无法写入新的队列元数据信息。

8.查看集群状态

指令rabbitmqctl cluster_status或者登陆管理界面查看如图

rabbitmq-manage

9.RabbitMQ镜像集群配置

上面已经完成RabbitMQ默认集群模式,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。虽然该模式解决一项目组节点压力,但队列节点宕机直接导致该队列无法应用,只能等待重启,所以要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群里的每个节点,必须要创建镜像队列。
镜像队列是基于普通的集群模式的,然后再添加一些策略,所以你还是得先配置普通集群,然后才能设置镜像队列,我们就以上面的集群接着做。

设置的镜像队列可以通过开启的网页的管理端,也可以通过命令,分别如下。
1.网页管理端创建rabbitmq策略
在mq01节点的控制台上创建策略
(1)点击admin菜单–>右侧的Policies选项–>左侧最下下边的Add/update a policy。
(2)按照图中的内容根据自己的需求填写。

  • Name:策略名称
  • Pattern:匹配的规则,^a这里表示匹配a开头的队列,如果是匹配所有的队列,那就是^.
  • Definition:使用ha-mode模式中的all,也就是同步所有匹配的队列。问号链接帮助文档。

(3)点击Add policy添加策略
此时分别登陆mq02、mq03两个节点的控制台,可以看到上面添加的这个策略

2.命令设置policy如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]

-p Vhost: 可选参数,针对指定vhost下的queue进行设置
Name: policy的名称
Pattern: queue的匹配模式(正则表达式)
Definition:镜像定义,包括三个部分ha-mode, ha-params, ha-sync-mode
ha-mode:指明镜像队列的模式,有效值为 all/exactly/nodes
all:表示在集群中所有的节点上进行镜像
exactly:表示在指定个数的节点上进行镜像,节点的个数由ha-params指定
nodes:表示在指定的节点上进行镜像,节点名称通过ha-params指定
ha-params:ha-mode模式需要用到的参数
ha-sync-mode:进行队列中消息的同步方式,有效值为automatic和manual
priority:可选参数,policy的优先级

例:rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic","ha-promote-on-shutdown":"always","ha-promote-on-failure":"always"}'

3.做破坏性测试
创建一个queue ab,像ab queue里发送一个message,自定义即可

1)将mq01节点的服务关闭,rabbitmqctl stop_app,再通过mq02和mq03查看消息记录是否还存在。从中可以看到ab队列已经从之前的+2显示成+1了,而且消息记录是存在的。

2)再将mq02节点的服务关闭,通过mq03查看消息记录是否还存在。从中可以看到ab队列和消息记录还是存在的,只是变成了一个节点了。

3)将mq01和mq02的服务再启动起来
从中可以看到ab队列后面+2变成了粉色,鼠标指上去显示镜像无法同步。如果这时候停掉mq03节点的服务,那么队列里面的消息将会丢失。

采取的解决办法是选择在mq02节点上执行同步命令。
rabbitmqctl sync_queue ab //同步ab队列

同步完成后,+2又变成了蓝色。
这样,我们就测试了rabbitmq集群的破坏性测试,说明集群配置成功。

10.其他功能指令使用

新增账户:

1
2
3
4
5
6
7
rabbitmqctl add_user barry barry@123
rabbitmqctl list_users
rabbitmqctl set_user_tags barry administrator
rabbitmqctl list_users
rabbitmqctl set_permissions -p / barry '.*' '.*' '.*'
rabbitmqctl list_permissions barry
rabbitmqctl list_user_permissions barry

设置服务开机自启动

1
systemctl enable rabbitmq-server  //关闭disable

查看并删除队列

1
2
rabbitmqctl list_queues
rabbitmqctl delete_queue ***队列名

11.rabbitmq网络分区配置-脑裂详解

集群和网络分区
RabbitMQ集群并不能很好的“忍受”网络分区。如果你想将RabbitMQ集群建立在广域网上,记住那是行不通的,除非你使用federation或者shovel等插件。然而有时候会有一些意想不到的事情发生。
RabbitMQ会将queues, exchanges, bindings等信息存储在Erlang的分布式数据库——Mnesia中,许多围绕网络分区的一些细节都和这个Mnesia的行为有关。
检测网络分区
如果另一个节点在一分钟(或者一个net_ticktime时间)内不能连接上一个节点,那么Mnesia通常任务这个节点已经挂了。就算之后两个节点连通(译者注:应该是指网络上的可连通),但是这两个节点都认为对方已经挂了,Mnesia此时认定发送了网络分区的情况。这些会被记录在RabbitMQ的日志中。
当一个节点起来的时候,RabbitMQ会记录是否发生了网络分区,你可以通过rabbitmqctl cluster_status这个命令或者管理插件看到相关信息。正常情况下,通过rabbitmqctl cluster_status命令查看到的信息中partitions那一项是空的。
然而当网络分区发生时,partitions内容就变了,同时管理界面也会有提示。
网络分区期间
当一个集群发生网络分区时,这个集群会分成两部分(或者更多),它们各自为政,互相都认为对方分区内的节点已经挂了, 包括queues, bindings, exchanges这些信息的创建和销毁都处于自身分区内,与其他分区无关。如果原集群中配置了镜像队列,而这个镜像队列又牵涉到两个(或者多个)网络分区的节点时,每一个网络分区中都会出现一个master节点(译者注:如果rabbitmq版本较新,分区节点个数充足,也会出现新的slave节点。),对于各个网络分区,此队列都是互相独立的。当然也会有一些其他未知的、怪异的事情发生。
当网络(这里只网络连通性,network connectivity)恢复时,网络分区的状态还是会保持,除非你采取了一些措施去解决他。
挂起/恢复导致的分区
当我们涉及到“网络分区”时,当集群中的不同的节点发生交互失败中断(communication interrupted)等,但是又没有节点挂掉这种情况下,才是发生了分区。然而除了网络失败(network failures)原因,操作系统的挂起或者恢复也会导致集群内节点的网络分区。因为发生挂起的节点不会认为自身已经失败或者停止工作,但是集群内的其他节点会这么认为。
如果一个集群中的一个节点运行在一台笔记本上,然后你合上了笔记本,这样这个节点就挂起了。或者说一种更常见的现象,节点运行在某台虚拟机上,然后虚拟机的管理程序挂起了这个虚拟机节点,这样也可能发生挂起。
由于挂起/恢复导致的分区并不对称——挂起的节点将看不到其他节点是否消失,但是集群中剩余的节点可以观察到,这一点貌似暗示了pause_minority这种模式(下面会涉及到)。
从网络分区中恢复
未来从网络分区中恢复,首先需要挑选一个信任的分区,这个分区才有决定Mnesia内容的权限,发生在其他分区的改变将不被记录到Mnesia中而直接丢弃。
停止(stop)其他分区的节点,然后启动(start)这些节点,之后重新将这些节点加入到当前信任的分区之中。
最后,你应该重启(restart)信任的分区中所有的节点,以去除告警。
你也可以简单的关闭整个集群的节点,然后再启动每一个节点,当然,你要确保你启动的第一个节点在你所信任的分区之中。
自动处理分区
RabbitMQ提供了三种方法自动的解决网络分区:pause-minority mode, pause-if-all-down mode以及autoheal mode。(默认的是ignore模式)
在pause-minority mode下,顾名思义,当发生网络分区时,集群中的节点在观察到某些节点“丢失”时,会自动检测其自身是否处于少数派(小于或者等于集群中一半的节点数),RabbitMQ会自动关闭这些节点的运作。根据CAP原理来说,这里保障了P,即分区耐受性(partition tolerance)。这样确保了在发生网络分区的情况下,大多数节点(当然这些节点在同一个分区中)可以继续运行。“少数派”中的节点在分区发生时会关闭,当分区结束时又会启动。
在pause-if-all-down mode下,RabbitMQ在集群中的节点不能和list中的任何节点交互时才会关闭集群的节点({pause_if_all_down, [nodes], ignore | autoheal},list即[nodes]中的节点)。也就是说,只有在list中所有的节点失败时才会关闭集群的节点。这个模式和pause-minority mode有点相似,但是,这个模式允许管理员的任命而挑选信任的节点,而不是根据上下文关系。举个案例,一个集群,有四个节点,2个节点在A机架上,另2个节点在B机架上,此时A机架和B机架的连接丢失,那么根据pause-minority mode所有的节点都将被关闭。
在autoheal mode下,当认为发生网络分区时,RabbitMQ会自动决定一个获胜(winning)的分区,然后重启不在这个分区中的节点。
一个获胜的分区(a winning partition)是指客户端连接最多的一个分区。(如果产生一个平局,即有两个(或多个)分区的客户端连接数一样多,那么节点数最多的一个分区就是a winning partition. 如果此时节点数也一样多,将会以一个未知的方式挑选winning partition.)
你可以通过在RabbitMQ配置文件中设置cluster_partition_handling参数使下面任何一种模式生效:
pause_minority
{pause_if_all_down, [nodes], ignore | autoheal}
autoheal
我该挑选那种模式?
有一点必须要清楚,允许RabbitMQ能够自动的处理网络分区并不一定会有正面的成效,也有能会带来更多的问题。网络分区会导致RabbitMQ集群产生众多的问题,你需要对你所遇到的问题作出一定的选择。就像本文开篇所说的,如果你置RabbitMQ集群于一个不可靠的网络环境下,你需要使用federation或者shovel插件。
你可能选择如下的恢复模式:
ignore: 你的网络很可靠,所有的节点都在一个机架上,连接在同一个交换机上,这个交换机也连接在WAN上,你不需要冒险而关闭部分节点。(或者适合只有两个节点的集群。)
pause_minority: 你的网络相对没有那么的可靠。比如你在EC2上建立了三个节点的集群,假设其中一个节点宕了,在这种策略下,剩余的两个节点还可以继续工作,失败的节点可以在恢复之后重新加入集群
autoheal: 你的网络非常不可靠,你更关心服务的连续性而不是数据的完整性。适合有两个节点的集群。
有关pause-minority模式的更多信息
关闭的RabbitMQ节点所在主机上的Erlang虚拟机还是在正常运行,但是此节点并不会监听任何端口也不会执行其他任务。这些节点每秒会检测一次剩下的集群节点是否会再次出现,如果出现,就启动自己继续运行。
注意上面所说的“关闭的RabbitMQ节点”并不会在启动时就进入关闭状态,即使它们在“少数派(minority)”。这些“少数派”可能在“剩余的集群节点”没有启动好之前就启动了。
同样需要注意的是RabbitMQ也会关闭不是严格意义上的“大多数(majority)”——数量超过集群的一半。因此在一个集群只有两个节点的时候并不适合采用pause-minority模式,因为由于其中任何一个节点失败而发生网络分区时,两个节点都会被关闭。然而如果集群中的节点个数远大于两个时,pause_minority模式比ignore模式更加的可靠,特别是网络分区通常是由于单个节点掉出网络。
最后,需要注意的是pause_minority模式将不会防止由于集群节点被挂起而导致的分区。这是因为挂起的节点将永远不会看到集群的其余部分的消失,因此将没有触发器将其从集群中断开。

文章目录
  1. 1. RabbiMQ简介
  2. 2. RabbiMQ模式
  3. 3. RabbiMQ特点
  4. 4. 搭建环境:
  5. 5. 搭建步骤
    1. 5.1. 1. 配置hosts文件
    2. 5.2. 2.安装erlang和rabbitmq-server软件
    3. 5.3. 3.修改rabbitmq config配置
    4. 5.4. 4. 安装管理插件
    5. 5.5. 5. 调整最大可打开文件句柄限制
    6. 5.6. 6.拷贝erlang.cookie
    7. 5.7. 7.将mq02、mq03作为内存节点加入mq01节点集群中
    8. 5.8. 8.查看集群状态
    9. 5.9. 9.RabbitMQ镜像集群配置
    10. 5.10. 10.其他功能指令使用
    11. 5.11. 11.rabbitmq网络分区配置-脑裂详解