一、为什么要使用集群?
集群是为了解决单机可能出现宕机等引发的不可用的问题,可以有效提高程序的可用性和可靠性以及抗并发的能力。
二、什么是Rabbitmq集群?
2.1、单一模式
即单机情况不做集群,就单独运行一个rabbitmq而已。
2.2、普通模式:
默认模式,以两个节点(rabbit01、rabbit02)为例来进行说明。对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01、rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer。所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么得等rabbit01节点恢复,然后才可被消费;如果没有持久化的话,就会产生消息丢失的现象。
2.3、镜像模式
把需要的队列做成镜像队列,存在与多个节点属于RabbitMQ的HA方案。该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。
三、怎么使用Rabbitmq集群?
3.1、集群的形成的条件
3.1.1、RabbitMQ集群的多种方式
- 通过在配置文件中列出群集节点进行声明
- 基于DNS的发现
- 使用AWS(EC2)实例发现(通过插件)
- 使用Kubernetes发现(通过插件)
- 基于Consul的发现(通过插件)
- 使用基于etcd的发现(通过插件)
- 使用rabbitmqctl手动
3.1.2、集群形成的必要条件
先准备三台服务器,修改hosts分别为node1,node2,node3。
- 第一步、主机名解析
node1服务器
vim /etc/hostname //在10.211.55.8设置域名为node1
vim /etc/hostname //在10.211.55.9设置域名为node2
vim /etc/hostname //在10.211.55.10设置域名为node2
vim / etc / hosts //分别配置node1、node2、node3的对应关系
10.211.55.8 node1
10.211.55.9 node2
10.211.55.10 node3
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
-
第二步、保证各个节点都一样的Erlang Cookie
RabbitMQ节点和CLI工具(例如rabbitmqctl)使用cookie来确定是否允许它们彼此通信。为了使两个节点能够通信,它们必须具有称为Erlang cookie的相同共享机密。Cookie只是一串字母数字字符,最大长度为255个字符。它通常存储在本地文件中。每个群集节点必须具有相同的cookie。
将node1的erlang.cookie拷贝到node2节点和node3节点。
scp /var/lib/rabbitmq/.erlang.cookie root@node2:/var/lib/rabbitmq/.erlang.cookie //拷贝到node2
scp /var/lib/rabbitmq/.erlang.cookie root@node3:/var/lib/rabbitmq/.erlang.cookie//拷贝到node3
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200726224055745.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmd1bzExMA==,size_16,color_FFFFFF,t_70)
- 第三步、将node2、node3服务加入到node1服务的集群中
# on node2
rabbitmqctl stop_app//停止当前节点的
# => Stopping node rabbit@node2 ...done.
rabbitmqctl reset
# => Resetting node rabbit@node2 ...
rabbitmqctl join_cluster rabbit@node1
# => Clustering node rabbit@node2 with [rabbit@node1] ...done.
rabbitmqctl start_app
# => Starting node rabbit@rabbit2 ...done.
# on node3
rabbitmqctl stop_app//停止当前节点的
# => Stopping node rabbit@node3 ...done.
rabbitmqctl reset
# => Resetting node rabbit@node3 ...
rabbitmqctl join_cluster rabbit@node1
# => Clustering node rabbit@node3 with [rabbit@node1] ...done.
rabbitmqctl start_app
# => Starting node rabbit@rabbit3...done.
需要注意的是rabbit@node2是node的规范名字,前面的rabbit是固定前缀。
- 第四步、查看状态,得到结果。
rabbitmqctl cluster_status//在node1节点查看状态
访问ip得到结果,访问ip得到结果,集群配置成功,但是这里第三个节点的rabbitmq应用没有启动成功。
经过一段实验发现,如果按照node1->node2->node3
的顺序启动,node3会启动失败;如果按照node2->node3->node1
或者node3->node2->node1
的顺序启动,三个节点是可以启动成功的。