RabbitMQ集群
rabbitMQ集群有两种模式:
第一种 普通模式:对于Queue来说,消息实体只存在于其中的一个节点,A/B两个节点仅有相同的元数据(队列结构)。也就是说数据存在于集群中某个节点,我们从另一个节点获取的时候是该节点和存储数据的节点临时进行传输。可以理解为A/B,搭建集群,数据存到A,我们从节点B可以获取到是B节点临时和A节点建立了数据通道从A获取数据,假设A节点宕机,则数据丢失。这种模式的话没有实现高可用。
第二种 镜像模式:也称为HA高可用模式,与普通集群模式区别 主要是消息实体会主动在镜像节点间同步数据,而不是只存储数据元信息。这种模式保证了HA,但是降低了系统性能,如果镜像队列过多,在消息大量进来的情况下,集群内部的网络带宽会被这种内部同步消耗掉,这种适用于可靠性要求较高的场景中。
下面研究镜像集群模式的搭建,还是以docker的形式进行搭建。
1.拉取镜像
docker pull hub.c.163.com/library/rabbitmq:management
2.创建容器,启动两个mq进程
1.容器1
$ docker run -d --hostname rabbitmq01 --name rabbitmqCluster01 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' hub.c.163.com/library/rabbitmq:management df45f88945b572ed8b23c8998db8819e7c7826ded2058ea235c2f04f775f4a2c
2.容器2
$ docker run -d --hostname rabbitmq02 --name rabbitmqCluster02 -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' --link rabbitmqCluster01:rabbitmq01 hub.c.163.com/library/rabbitmq:management 1f18cbceb309d9ac3f723563151d81f18955b1e5534f23222b3e92cba57dbb86
参数解释:
-d: 后台运行容器,并返回容器ID; --hostname rabbitmq02 指定容器的hostname --name="rabbitmqCluster02": 为容器指定一个名称; -p 外部端口:内部端口,是将端口做映射。15672是管理界面端口,5672是客户端通讯接口 -e 设置环境变量 --link=[]: 添加链接到另一个容器;也就是使得两个容器可以通信
这里解释下。-e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' 是设置环境变量。ErlangCookie是保证不同节点间可以互相通信的密钥,要保证不同节点间可以互相通信必须保证共享相同的Erlang Cookie,在容器内部的话是放在/var/lib/rabbitmq/.erlang.cookie
进入容器内部查看:
root@rabbitmq02:/# cat /var/lib/rabbitmq/.erlang.cookie rabbitmqCookie
3.启动后应该通过15672端口和15673端口都可以访问到management控制台
4.容器节点加入集群
1.对节点1设置
(1)进入容器1,也就是rabbitmq01
$ docker exec -it df bash
(2) 停止服务、清数据、重启
root@rabbitmq01:/# rabbitmqctl stop_app #停服务 Stopping rabbit application on node rabbit@rabbitmq01 root@rabbitmq01:/# rabbitmqctl reset #清掉数据 Resetting node rabbit@rabbitmq01 root@rabbitmq01:/# rabbitmqctl start_app 重启 Starting node rabbit@rabbitmq01
2.对节点2设置
(1)进入容器
$ docker exec -it 1f /bin/bash
(2)加入集群
root@rabbitmq02:/# rabbitmqctl stop_app Stopping rabbit application on node rabbit@rabbitmq02 root@rabbitmq02:/# rabbitmqctl reset Resetting node rabbit@rabbitmq02 root@rabbitmq02:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq01 Clustering node rabbit@rabbitmq02 with rabbit@rabbitmq01 root@rabbitmq02:/# rabbitmqctl start_app Starting node rabbit@rabbitmq02
rabbitmqctl join_cluster --ram rabbit@rabbitmq01 是加入集群,rabbitmq01 是另一个节点的hostname。
补充:如果还有第三个节点加入集群,也是用上面的方式加入集群
5.到管理端查看,可以看到节点信息
6. 增加一个策略,设置集群镜像模式
可以到控制台设置,也可以到界面设置。这里在控制台设置:
root@rabbitmq01:/# rabbitmqctl set_policy ha "^" '{"ha-mode":"all"}' Setting policy "ha" for pattern "^" to "{\"ha-mode\":\"all\"}" with priority "0"
到界面查看:
到此集群搭建完成。
7.Springboot连接集群
只需要修改连接地址就可以了,如下:
#cluster spring.rabbitmq.addresses=192.168.99.100:5672,192.168.99.100:5673 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
8. 补充: 三个集群节点补充
1. 新起三个docker 容器
xxx@A022296-NC01 MINGW64 ~ $ docker run -d --hostname rabbitmq01 --name rabbitmqCluster01 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' hub.c.163.com/library/rabbitmq:management 932b8518e782ae7a4ef1e85b9210d205af180609bc0974699c805f9015d37fb5 xxx@A022296-NC01 MINGW64 ~ $ docker run -d --hostname rabbitmq02 --name rabbitmqCluster02 -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' --link rabbitmqCluster01:rabbitmq01 hub.c.163.com/library/rabbitmq:management c6f5a0a8561024b352abfded4332a8b954f555672120f9c856ff5093373ce48b xxx@A022296-NC01 MINGW64 ~ $ docker run -d --hostname rabbitmq03 --name rabbitmqCluster03 -p 15674:15672 -p 5674:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' --link rabbitmqCluster01:rabbitmq01 --link rabbitmqCluster02:rabbitmq02 hub.c.163.com/library/rabbitmq:management ae84596ed05e39d564f7b22270dd2c96fa2fd6c072ee01897cba84116e1fc18e
2. 第二个加入集群
$ docker exec -it c6 bash root@rabbitmq02:/# rabbitmqctl stop_app Stopping rabbit application on node rabbit@rabbitmq02 root@rabbitmq02:/# rabbitmqctl reset Resetting node rabbit@rabbitmq02 root@rabbitmq02:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq02 Clustering node rabbit@rabbitmq02 with rabbit@rabbitmq01 root@rabbitmq02:/# rabbitmqctl start_app Starting node rabbit@rabbitmq02
3. 第三个加入集群
$ docker exec -it ae bash root@rabbitmq03:/# rabbitmqctl stop_app Stopping rabbit application on node rabbit@rabbitmq03 root@rabbitmq03:/# rabbitmqctl reset Resetting node rabbit@rabbitmq03 root@rabbitmq03:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq02 Clustering node rabbit@rabbitmq03 with rabbit@rabbitmq02 root@rabbitmq03:/# rabbitmqctl start_app Starting node rabbit@rabbitmq03
4. 查看集群状态:
root@rabbitmq03:/# rabbitmqctl cluster_status Cluster status of node rabbit@rabbitmq03 [{nodes,[{disc,[rabbit@rabbitmq01]}, {ram,[rabbit@rabbitmq03,rabbit@rabbitmq02]}]}, {running_nodes,[rabbit@rabbitmq02,rabbit@rabbitmq01,rabbit@rabbitmq03]}, {cluster_name,<<"rabbit@rabbitmq01">>}, {partitions,[]}, {alarms,[{rabbit@rabbitmq02,[]}, {rabbit@rabbitmq01,[]}, {rabbit@rabbitmq03,[]}]}]
5. 关于节点类型
在集群中声明(declare)创建exchange queue binding,这类操作要等到所有的节点都完成创建才会返回:如果是内存节点就要修改内存数据,如果是disk node 就要等待写磁盘,节点过多这里的速度就会被大大的拖慢。只要有一个节点是Disc Node 就能提供条件把集群元数据写到磁盘,RabbitMQ的确也是这样要求的:集群中只要有一个disk node就可以,其它的都可以是RAM node.节点加入或退出集群一定至少要通知集群中的一个disk node,来记录这种变动.
6. 总结:
现在搭建的集群是默认的普通集群,集群中节点可以共享集群中的exchange,routingKey和queue,但是queue中的消息只保存在首次声明queue的节点中。通过其他节点获取队列消息的时候是节点从队列所在节点获取到自己内存中然后返回给客户端。因为queue中的消息只保存在首次声明queue的节点中,这样就个问题:如果某一个node节点挂掉了,那么只能等待该节点重新连接才能继续处理该节点内的消息(如果没有设置持久化的话,节点挂掉后消息会直接丢失)。测试可以创建一个队列, 创建的时候需要选择所在的节点,发送一些消息后让该节点下线, 会导致该队列不可用。 也可以到每个集群节点内部查看队列数量:
root@rabbitmq01:~/mnesia/rabbit@rabbitmq01# pwd /var/lib/rabbitmq/mnesia/rabbit@rabbitmq01 root@rabbitmq01:~/mnesia/rabbit@rabbitmq01# ls -l total 108 -rw-r--r-- 1 rabbitmq rabbitmq 160 Nov 22 09:07 DECISION_TAB.LOG -rw-r--r-- 1 rabbitmq rabbitmq 96 Nov 22 09:07 LATEST.LOG -rw-r--r-- 1 rabbitmq rabbitmq 79 Nov 22 09:04 cluster_nodes.config drwxr-xr-x 2 rabbitmq rabbitmq 4096 Nov 22 09:04 msg_store_persistent drwxr-xr-x 2 rabbitmq rabbitmq 4096 Nov 22 09:04 msg_store_transient -rw-r--r-- 1 rabbitmq rabbitmq 57 Nov 22 09:04 nodes_running_at_shutdown drwxr-xr-x 3 rabbitmq rabbitmq 4096 Nov 22 08:29 queues -rw-r--r-- 1 rabbitmq rabbitmq 1323 Nov 22 09:04 rabbit_durable_exchange.DCD -rw-r--r-- 1 rabbitmq rabbitmq 250 Nov 22 09:04 rabbit_durable_queue.DCD -rw-r--r-- 1 rabbitmq rabbitmq 329 Nov 22 09:07 rabbit_durable_queue.DCL -rw-r--r-- 1 rabbitmq rabbitmq 230 Nov 22 09:04 rabbit_durable_route.DCD -rw-r--r-- 1 rabbitmq rabbitmq 163 Nov 22 09:04 rabbit_runtime_parameters.DCD -rw-r--r-- 1 rabbitmq rabbitmq 3 Nov 22 09:04 rabbit_serial -rw-r--r-- 1 rabbitmq rabbitmq 227 Nov 22 09:04 rabbit_user.DCD -rw-r--r-- 1 rabbitmq rabbitmq 190 Nov 22 09:04 rabbit_user_permission.DCD -rw-r--r-- 1 rabbitmq rabbitmq 131 Nov 22 09:04 rabbit_vhost.DCD -rw-r--r-- 1 rabbitmq rabbitmq 5464 Nov 22 09:04 recovery.dets -rw-r--r-- 1 rabbitmq rabbitmq 25778 Nov 22 08:33 schema.DAT -rw-r--r-- 1 rabbitmq rabbitmq 285 Nov 22 03:06 schema_version
可以到queues 目录下查看相关队列信息。也可以到每个主机上执行下面命令查看队列:
rabbitmqctl list_queues --local
7. 配置镜像队列
镜像队列是在普通集群搭建后,通过设置同步策略来实现的。在任何一台机子执行下面命令:
rabbitmqctl set_policy ha-all "^my" '{"ha-mode":"all","ha-sync-mode":"automatic"}' # rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority] # ha-all:为策略名称; # ^my:为匹配符,只有一个^代表匹配所有,^abc为匹配名称以abc开头的queue或exchange; # ha-mode:为同步模式,一共3种模式: # ①all-所有(所有的节点都同步消息), # ②exctly-指定节点的数目(需配置ha-params参数,此参数为int类型比如2,在集群中随机抽取2个节点同步消息) # ③nodes-指定具体节点(需配置ha-params参数,此参数为数组类型比如["rabbit@rabbitmq1","rabbit@rabbitmq2"],明确指定在这两个节点上同步消息)。 # ha-sync-mode:进行队列中消息的同步方式,有效值为automatic和manual
或者web中Admin -> Policies 设置
查看策略:
root@rabbitmq02:~/mnesia# rabbitmqctl list_policies Listing policies / ha-all all ^ {"ha-mode":"all","ha-sync-mode":"automatic"} 0
8. 测试新建一个队列myqueue, 可以看到会采用上面的策略, 并且在node1 挂掉后会自动切换node2 继续提供服务。
参考: https://www.rabbitmq.com/clustering.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2017-11-08 自己打断点走的struts流程&拦截器工作原理
2017-11-08 redis可视化界面的操作【二十一】
2017-11-08 struts面试题及答案【重要】
2017-11-08 struts2的核心和工作原理
2017-11-08 Java操作redis【二十】
2017-11-08 优化【十九】
2017-11-08 管线【十八】