RabbitMQ 之集群搭建

配置集群主要一定是在局域网配置,RabbitMQ集群对延迟非常敏感,在广域网中不应该使用集群而是使用 Federation 和 Shovel 来代替
多机集群

一、修改 /etc/hosts 文件,在其上添加 IP 地址与节点 名称的映射信息

vim /etc/hosts
192.168.0.2 node1
192.168.0.3 node2 
192.168.0.4 node3 

二、编辑RabbitMQ的cookie文件,以确保各个节点的cookie文件使用的是同一个值。

可以读取node1节点的值,然后将其复制到node2和node3节点中。cookie文件默认路径为 /var/lib/rabbitmq/.erlang.cookie 或者 $HOME/.erlang.cookie 。cookie相当于令牌,集群种的 rabbitmq 节点需要通过交换令牌以获得相互认证。如果节点的秘钥认证不一致,那么在配置节点就会有如下报错:

./rabbitmqctl join_cluster rabbit@node1 
Authentication failed (rejected by the remote node) , please check the Erlanq cookie 

三、配置集群

配置集群有三种方式:
1.通过 rabbitmqctl 工具配置
2.通过 rabbitmq.conf 配置文件配置
3.通过 rabbitmq-autocluster 插件配置
用的最多的 还是第一种配置方式,配置方式如下:
1.首先启动node1、node2、node3 3个节点的服务,启动后可以通过 ./rabbitmqctl cluster_status 查看每个节点集群的状态
2.以 node1节点为基准,将 node2、node3 节点加入到 node1 节点的集群中,这三个节点是平等的,如果想调换彼此的加入顺序也未尝不可。首先将 node2 节点加入到 node1节点的集群中,需要执行如下4个命令。

[root@node2 -]# ./rabbitmqctl stop_app
Stopping rabbit application on node rabbit@node2 
[root@node2 -]# ./rabbitmqctl reset 
Resetting node rabb t@node2
[root@node2 -]# ./rabbitmqctl join_cluster rabbit@nodel 
Clustering node rabbit@node2 with rabbit@nodel 
[root@node2 -]# ./rabbitmqctl start_app
Starting node rabbit@node2

./rabbitmqctl cluster_status 查看集群状态
最后将 node3 也同样加进去即可。
当三个集群都成功搭建,查看状态应该如下:

[{nodes, [{disc , [rabbit@nodel , rabbit@node2 , rabbit@node3]}]} , 
{running_nodes, [rabbit@node l , rabbit@node2 , rabbit@node3]} , 
{cluster_name , << " rabbit@nodel " >> } , 
{partitions, []}, 
{alarms, [{ rabbit@nodel , [] } , {rabbi t@node2 , []} , {rabbi t@node3 , [] }]}] 

如果停止node2集群,则在 running_nodes 中少掉 node2这个节点信息

如果关闭了集群中的所有节点,则需要确保在启动的时候最后关闭的那个节点是第一个启动的。如果第一个启动的不是最后关闭的节点,那么这个节点会等待最后关闭的节点启动。这 个等待时间是 30 秒,如果没有等到,那么这个先启动的节点也会失败。在最新的版本中会有重 试机制 默认重试 10 次 30 秒以等待最后关闭的节点启动。

在重试失败之后,当前节点也会因失败而关闭自身的应用。比如 node1 节点最后关闭,那么此时先启动 node2 节点,在等待若干时间之后发现 node1 还是没有启动,这会报如下错:

Timeout contacting cluster nodes: [rabbit@node1]. 

如果最后一个关闭的节点最终由于某些异常而无法启动,则可以通过 rabbitrnqctl forget_cluster_node 命令来将此节点剔出当前集群。如果集 群中的所有节点由于某些非正常因素,比如断电而关闭,那么集群中的节点都会认为还有其他 节点在它后面关闭,此时需要调用 rabbitrnqctl force_boot 命令来启动一个节点,之后 集群才能正常启动。

四、集群节点类型

集群节点类型分为:磁盘类型、内存类型。内存类型可以获得更高的性能。

./rabbitmqctl cluster_status
[{nodes, [{disc , [rabbit@nodel , rabbit@node2 , rabbit@node3]}]} , 
{running_nodes, [rabbit@node l , rabbit@node2 , rabbit@node3]} , 
{cluster_name , << " rabbit@nodel " >> } , 
{partitions, []}, 
{alarms, [{ rabbit@nodel , [] } , {rabbi t@node2 , []} , {rabbi t@node3 , [] }]}] 

其中 disc 标注了 RabbitMQ 节点的类型。
将 node2 节点加入 node1 节点时候,指定node2节点为内存节点,如下:
默认不添加 --ram 参数则表示节点为磁盘节点。

[root@node2 -]# ./rabbitmqctl join_cluster rabbit@nodel --ram 
Clustering node rabbit@node2 with rabbit@nodel  
[root@node2 -]# ./rabbitmqctl cluster_status
[{nodes, [{disc , [rabbit@nodel]} , {ram,[rabbit@node2]}]} , 
{running_nodes, [rabbit@nodel , rabbit@node2]} ,
{cluster_name , <<"rabbit@nodel">>} , 
{partittions, [] } ,
{alarms, [ {rabbi t@nodel , [] }, {rabbit@node2 , [] }]}] 

如果节点已经搭建好了,那么也可以使用 rabbitmqctl change_cluster_node_type {disc,ram} 命令来切换节点类型,其中 disc 表示磁盘节点,而 ram 表示内存节点。如下把 node2 节点转变磁盘节点。

[root@node2 -]# ./rabbitmqctl stop_app 
Stopping rabbit application on node rabbit@node2 
[root@node2 -]# ./rabbitmqctl change_cluster_node_type disc
Turning rabbit@node2 into a disc node  
[root@node2 -]# ./rabbitmqctl start_app 
Starting node rabbit@node2 
[root@node2 -]# ./rabbitmqctl cluster_status
[{nodes, [{disc , [rabbit@nodel , rabbit@node2] }] },
{running_nodes, [rabbit@nodel , rabbit@node2]} , 
{cluster name , << " rabbit@nodel">>} , 
{partitions, []} , 
{alarms, [{rabbit@nodel , []}, {rabbit@node2 , []}]}] 

RabbitMQ 只要求在集群中至少有一个磁盘节点,所有其他节点可以是内存节点。当节点加 入或者离开集群时,它们必须将变更通知到至少一个磁盘节点。如果只有一个磁盘节点,而且 不凑巧的是它刚好崩溃了,那么集群可以继续发送或者接收消息,但是不能执行创建队列、交换器、绑定关系、用户,以及更改权限、添加或删除集群节点的操作了。也就是说,如果集群 中唯一的磁盘节点崩溃,集群仍然可以保持运行,但是直到将该节点恢复到集群前,你无法更 改任何东西。所以在建立集群的时候应该保证有两个或者多个磁盘节点的存在。

在内存节点重启后,它们会连接到预先配置的磁盘节点,下载当前集群元数据的副本。当 在集群中添加内存节点时,确保告知其所有的磁盘节点(内存节点唯一存储到磁盘的元数据信 息是集群中磁盘节点的地址)。只要内存节点可以找到至少一个磁盘节点,那么它就能在重启后 重新加入集群中。

除非使用的是 RabbitMQ 的 RPC 功能,否则创建队列、交换器及绑定关系的操作确是甚少, 大多数的操作就是生产或者消费消息。为了确保集群信息的可靠性,或者在不确定使用磁盘节 点或者内存节点的时候,建议全部使用磁盘节点。

五、剔除单个节点

第一种方式:
在需要剔除的节点上键入 ./rabbitmqctl stop_app 或者 ./rabbitmqctl stop 命令来关闭Rabbitmq服务。之后在别的节点上执行 ./rabbitmqctl forget_cluster_node 剔除的节点名称 进行节点剔除。(这种方式出于节点都在运行的状态,而剔除节点需要先停止,然后再另一个节点进行剔除操作,其余节点也就同步了)
当所有节点都停止运行了,剔除节点只需要 执行如下:

./rabbitmqctl forget_cluster_node 剔除的节点名称 --offline

注意上面在使用 ./rabbitmqctl forget_cluster_node 命令的时候用到了 --offline 参数,如果不添加这个参数,就需要保证 执行命令的 节点中的RabbitMQ服务出于运行状态,而在这种情况下,如果执行的 命令节点 依赖于其他节点(这里说下 所有节点关闭,启动时,最后一个关闭的节点必须第一个启动,否则启动其他节点会报错。),则 --offline 参数的添加让其可以在非运行状态下将 需剔除的节点 剔离当前集群。

第二种方式:
在需要剔除的节点上执行 ./rabbitmqctl reset 如果不是像上面由于启动顺序的缘故而不得不删除一个集群节点,建议采用这种方式。
正如之前所说的, rabbitmqctl reset 命令将清空节点的状态,并将其恢复到空白状态。 当重设的节点是集群中的一部分时,该命令也会和集群中的磁盘节点进行通信,告诉它们该节点正在离开集群。不然集群会认为该节点出了故障,并期望其最终能够恢复过来。

六、集群节点的升级

如果 RabbitMQ 集群由单独的一个节点组成,那么升级版本很容易,只需关闭原来的服务, 然后解压新的版本再运行即可。不过要确保原节点的 Mnesia 中的数据不被变更,且新节点中的 Mnesia 路径的指向要与原节点中的相同。或者说保留原节点 Mnesia 数据,然后解压新版本到相应的目录,再将新版本的 Mnesia 路径指向保留的 Mnesia 数据的路径(也可以直接复制保留的 Mnesia 数据到新版本中相应的目录) ,最后启动新版本的服务即可。

如果 RabbitMQ 集群由多个节点组成,那么也可以参考单个节点的情形。具体步骤:

(1)关闭所有节点的服务,注意采用 rabbitmqctl stop 命令关闭。
(2)保存各个节点的 Mnesia 数据。
(3)解压新版本的 RabbitMQ 到指定的目录。
(4)指定新版本的 Mnesia 路径为步骤 2 中保存的 Mnesia 数据路径。
(5)启动新版本的服务,注意先重启原版本中最后关闭的那个节点。
其中步骤 4 和步骤 5 可以一起操作,比如执行 RABBITMQ_MNESIA_BASE=/opt/mnesia rabbitmq-server-detached 命令,其中 /opt/mnesia 为原版本保存Mnesia 数据的路径。

RabbitMQ 的版本有很多,难免会有数据格式不兼容的现象,这个缺陷在越旧的版本中越发凸显,所以在对不同版本升级的过程中,最好先测试两个版本互通的可能性,然后再在线上环 境中实地操作。

如果原集群上的配置和数据都可以舍弃,则可以删除原版本的 RabbitMQ ,然后再重新安装 配置即可;如果配置和数据不可丢弃 ,则保存元数据,之后再关闭所有生产者 并等待消费者消费完队列中的所有数据,紧接着关闭所有消费者,然后重新安装 RabbitMQ 并重建元数据等。

当然如果有个新版本的集群,那么从旧版本迁移到新版本的集群中也不失为一个升级的好办法。

你可能感兴趣的:(RabbitMQ 之集群搭建)