RabbiMQ 是用 Erlang 开发的, 集群非常方便, 因为 Erlang 天生就是一门分布式语言, 但其本身并不支持负载均衡。
RabbitMQ 集群中节点包括内存节点(RAM)、 磁盘节点(Disk, 消息持久化), 集群中至少有一个 Disk 节点。
对于普通模式, 集群中各节点有相同的队列结构, 但消息只会存在于集群中的一个节点。 对于消费者来说, 若消息进入 A 节点的 Queue 中, 当从 B 节点拉取时, RabbitMQ 会将消息从 A 中取出, 并经过 B 发送给消费者。
应用场景: 该模式各适合于消息无需持久化的场合, 如日志队列。 当队列非持久化, 且创建该队列的节点宕机, 客户端才可以重连集群其他节点, 并重新创建队列。 若为持久化,只能等故障节点恢复。
与普通模式不同之处是消息实体会主动在镜像节点间同步, 而不是在取数据时临时拉取, 高可用; 该模式下, mirror queue 有一套选举算法, 即 1 个 master、 n 个 slaver, 生产者、 消费者的请求都会转至 master。
应用场景: 可靠性要求较高场合, 如下单、 库存队列。
缺点: 若镜像队列过多, 且消息体量大, 集群内部网络带宽将会被此种同步通讯所消耗。
(1) 镜像集群也是基于普通集群, 即只有先搭建普通集群, 然后才能设置镜像队列。
(2) 若消费过程中, master 挂掉, 则选举新 master, 若未来得及确认, 则可能会重复消费。
#创建rabbitmq用于存放rabbitmq集群映射信息
mkdir /mydata/rabbitmq
#分别创建各集群映射目录
cd rabbitmq/
mkdir rabbitmq01 rabbitmq02 rabbitmq03
rabbitmq01
docker run -d --hostname rabbitmq01 --name rabbitmq01 -v /mydata/rabbitmq/rabbitmq01:/var/lib/rabbitmq -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='zr' rabbitmq:3.8.2-management
rabbitmq02
docker run -d --hostname rabbitmq02 --name rabbitmq02 -v/mydata/rabbitmq/rabbitmq02:/var/lib/rabbitmq -p 15674:15672 -p 5674:5672 -e RABBITMQ_ERLANG_COOKIE='zr' --link rabbitmq01:rabbitmq01 rabbitmq:3.8.2-management
rabbitmq03
docker run -d --hostname rabbitmq03 --name rabbitmq03 -v /mydata/rabbitmq/rabbitmq03:/var/lib/rabbitmq -p 15675:15672 -p 5675:5672 -e RABBITMQ_ERLANG_COOKIE='zr' --link rabbitmq01:rabbitmq01 --link rabbitmq02:rabbitmq02 rabbitmq:3.8.2-management
注意事项:
–hostname 设置容器的主机名
RABBITMQ_ERLANG_COOKIE
节点认证作用, 部署集成时 需要同步该值RABBITMQ_ERLANG_COOKIE 为rabbitmq多节点之间通信所用到的cookie,rabbitmq集群就是利用这一特性实现的
启动成功后
http://192.168.157.128:15673/#/
http://192.168.157.128:15674/#/
http://192.168.157.128:15675/#/
账号:guest
密码:guest
登录查看一下,目前都是单节点
设置rabbitmq01为主节点
docker exec -it rabbitmq01 /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
Exit
如果出现以下情况说明rabbitmq版本太高了,新拉一个镜像3.8.2(老师对应的),当然也可以按照高版本的配置
docker pull rabbitmq:3.8.2
将rabbitmq02加入rabbitmq01
docker exec -it rabbitmq02 /bin/bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit
将rabbitmq02加入rabbitmq01
docker exec -it rabbitmq03 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit
最后能看到其他节点信息也就成功了(普通模式)
说明一下端口15673为rabbitmq01 ,15674为rabbitmq02,15675为rabbitmq03
在rabbitmq01新建test队列
在rabbitmq01新建test交换机,并绑定关系
同时发现rabbitmq02,rabbitmq03中也创建了相同的交换机,队列,绑定关系
向rabbitmq01的交换机发送消息
在rabbitmq02 rabbitmq03中也能拿到消息
在一个节点中消费了该消息,其他节点中将不会存在该消息
在普通模式集群的条件下才能搭建镜像集群,并且需要选择一个主节点,此处我们选择rabbitmq01为主节点
#进入rabbitmq01容器
docker exec -it rabbitmq01 bash
首先查看此时的策略什么,发现为空,默认普通模式
rabbitmqctl list_policies -p /
增加镜像模式策略
策略模式 all 即复制到所有节点, 包含新增节点,
策略正则表达式为 “^” 表示所有匹配所有队列名称。
“^hello”表示只匹配名为 hello 开始的队列
rabbitmqctl set_policy -p / ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
查看此时的策略
管理页面查看
再次向rabbitma01的test交换机发送信息,正常情况与普通模式一致
当我向rabbitma01发送消息后,宕机了,普通模式由于本质是其他节点比如rabbitma02去拿rabbitma01的消息再转交给我,所以当rabbitma01宕机后就拿不到消息了.
镜像模式由于是同步的,当rabbitma01宕机后客户端是直接可以向其他节点拿到消息的
(个人理解普通模式就是代理,源头断了也就什么都没有了;镜像模式就是复制cv,一个地方断掉了,但是还可以从其他地方还能拿到)