RabbitMQ 集群搭建
目录
- RabbitMQ 集群搭建
- 序言
- 系统环境
- 单节点安装
- 配置集群
序言
在生产环境中经常会遇到服务器断电、主板故障,吞吐量猛增,内存不足、磁盘不足等情况,单机节点的rabbitmq显然无能为力,这时需要搭建一个RabbitMQ集群来解决这些问题。
通过 Erlang 的分布式特性创建RabbitMQ 集群,各 RabbitMQ 服务为对等节点,即每个节点都提供服务给客户端连接,进行消息发送与接收。集群间共享用户、vhost、队列,交换器、绑定和运行时参数
- 在单个节点崩溃的情况下,消费者和生产者可以重新连接到集群的任何节点继续生产或消费
- 集群并不能保证消息万无一失,即将消息、队列、交换器等都设置为可持久化,生产端和消费端都正确地使用了确认方式,当集群中一个节点崩溃,该节点所有队列中的消息也都将丢失。 (可通过配置镜像队列解决)
原因:
基于存储空间和对性能的考虑,集群只会在单个节点而不是所有节点上创建队列的进程并包含完整的信息(元数据、状态及内容)。其他节点只知道队列的元数据和指向该队列存在节点的指针 - 集群所有节点都会备份的元数据信息
- 队列元数据:队列的名称及属性
- 交换器:交换器的名称及属性
- 绑定关系元数据:交换器与队列或者交换器与交换器之间的绑定关系
- vhost元数据:为vhost内的队列、交换器和绑定提供命名空间及安全属性
- 集群节点类型
- 磁盘节点
- 内存节点
Rabbitmq要求在集群中至少有一个磁盘节点。当节点加入或离开集群时,至少要通知到一个磁盘节点。如果只有一个磁盘节点,又正好崩溃了,那集群可以继续发送和接受消息,但不能执行创建队列、交换器、绑定关系、用户,以及更改权限、添加或删除集群节点的操作。在创建集群时应该保证有两个磁盘节点,建议全部使用磁盘节点。
磁盘节点的作用?
内存节点重启后,会连接到之前配置的磁盘节点,下载集群元数据的副本。
当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01、rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer。所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。
系统环境
主机名 | IP | 系统 |
node1 | 192.168.49.135 | CentOS Linux release 7.6.1810 (Core) |
node2 | 192.168.49.136 | CentOS Linux release 7.6.1810 (Core) |
node3 | 192.168.49.137 | CentOS Linux release 7.6.1810 (Core) |
单节点安装
配置集群
- 配置各主机hosts文件,让各个节点可以通过主机名识别对方
[root@node1 ~]# vim /etc/hosts
[root@node1 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.49.135 node1
192.168.49.136 node2
192.168.49.137 node3
[root@node1 ~]#
- RabbitMQ的集群依赖erlang集群,而erlang集群是通过这个cookie进行通信认证的,因此 编辑erlang的cookie文件,确保各个节点的cookie相同
erlang.cookie的位置
- /var/lib/rabbitmq/.erlang.cookie
或 - $HOME/.erlang.cookie
【注】 先停止rabbitmq,在更改erlang.cookie的值,不然报错
[root@node1 ~]# cat .erlang.cookie
NDBXFMHEOCACWFPUGUYV[root@node1 ~]#
#将.erlang.cookie 复制到其他节点过程略
[root@node1 ~]# cat .erlang.cookie
NDBXFMHEOCACWFPUGUYV[root@node1 ~]#
[root@node2 ~]# cat .erlang.cookie
NDBXFMHEOCACWFPUGUYV
[root@node2 ~]#
[root@localhost ~]# cat .erlang.cookie
NDBXFMHEOCACWFPUGUYV
[root@node3 ~]#
- 启动各节点rabbitmq服务
[root@node1 ~]# rabbitmq-server -detached
[root@node2 ~]# rabbitmq-server -detached
[root@node3 ~]# rabbitmq-server -detached
通过日志判断各节点cookie hash是否一致
2019-05-29 00:21:36.524 [info] <0.241.0>
node : rabbit@node1
home dir : /root
config file(s) : /opt/rabbitmq_server-3.7.15/etc/rabbitmq/rabbitmq.conf
cookie hash : d/zE3xrt478dueqdlI+ZiA==
log(s) : /opt/rabbitmq_server-3.7.15/var/log/rabbitmq/rabbit@node1.log
: /opt/rabbitmq_server-3.7.15/var/log/rabbitmq/rabbit@node1_upgrade.log
database dir : /opt/rabbitmq_server-3.7.15/var/lib/rabbitmq/mnesia/rabbit@node1
2019-05-29 00:42:12.652 [info] <0.289.0>
node : rabbit@node2
home dir : /root
config file(s) : (none)
cookie hash : d/zE3xrt478dueqdlI+ZiA==
log(s) : /opt/rabbitmq_server-3.7.15/var/log/rabbitmq/rabbit@node2.log
: /opt/rabbitmq_server-3.7.15/var/log/rabbitmq/rabbit@node2_upgrade.log
database dir : /opt/rabbitmq_server-3.7.15/var/lib/rabbitmq/mnesia/rabbit@node2
2019-05-29 00:42:14.563 [info] <0.289.0>
node : rabbit@node3
home dir : /root
config file(s) : (none)
cookie hash : d/zE3xrt478dueqdlI+ZiA==
log(s) : /opt/rabbitmq_server-3.7.15/var/log/rabbitmq/rabbit@node3.log
: /opt/rabbitmq_server-3.7.15/var/log/rabbitmq/rabbit@node3_upgrade.log
database dir : /opt/rabbitmq_server-3.7.15/var/lib/rabbitmq/mnesia/rabbit@node3
这三个节点目前都是以独立的集群,通过命令来查看他们的状态
[root@node1 rabbitmq]# rabbitmqctl cluster_status
Cluster status of node rabbit@node1 ...
[{nodes,[{disc,[rabbit@node1]}]},
{running_nodes,[rabbit@node1]},
{cluster_name,<<"rabbit@node1">>},
{partitions,[]},
{alarms,[{rabbit@node1,[]}]}]
[root@node1 rabbitmq]#
[root@node2 rabbitmq]# rabbitmqctl cluster_status
Cluster status of node rabbit@node2 ...
[{nodes,[{disc,[rabbit@node2]}]},
{running_nodes,[rabbit@node2]},
{cluster_name,<<"rabbit@node2">>},
{partitions,[]},
{alarms,[{rabbit@node2,[]}]}]
[root@node3 rabbitmq]# rabbitmqctl cluster_status
Cluster status of node rabbit@node3 ...
[{nodes,[{disc,[rabbit@node3]}]},
{running_nodes,[rabbit@node3]},
{cluster_name,<<"rabbit@node3">>},
{partitions,[]},
{alarms,[{rabbit@node3,[]}]}]
- 以node1节点为基准,将node2,node3加入node1节点的集群(顺序可调换)
在node2,node3 执行如下命令
[root@node2 rabbitmq]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@node2 ...
[root@node2 rabbitmq]# rabbitmqctl reset
Resetting node rabbit@node2 ...
[root@node2 rabbitmq]# rabbitmqctl join_cluster rabbit@node1
Clustering node rabbit@node2 with rabbit@node1
[root@node2 rabbitmq]# rabbitmqctl start_app
Starting node rabbit@node2 ...
completed with 0 plugins.
[root@node2 rabbitmq]#
此时在查看集群状态:
[root@node3 rabbitmq]# rabbitmqctl cluster_status
Cluster status of node rabbit@node3 ...
[{nodes,[{disc,[rabbit@node1,rabbit@node2,rabbit@node3]}]},
{running_nodes,[rabbit@node1,rabbit@node2,rabbit@node3]},
{cluster_name,<<"rabbit@node1">>},
{partitions,[]},
{alarms,[{rabbit@node1,[]},{rabbit@node2,[]},{rabbit@node3,[]}]}]
[root@node3 rabbitmq]#
可以看到node2,node3已经加入集群