目的
在此前的实验中发现一个现象,感觉有些奇怪,所以设立此实验进行验证,现象是:用程序建 Q 之后后再建镜像策略,Q master 在原来的节点上,而策略所指定的节点成为从节点。但是在控制台上建的 Q 在策略生效后 Q master 会自动跳到镜像内的节点上。
在多次实验后发现,主队列是否会依照策略所指定的节点变化,不取决于 队列 与 策略 创建的顺序,也不取决于队列是由控制台创建的还是由程序创建的。发生上述现象的原因是:代码在创建队列后随即就向队列里面写入消息。之后建立策略,Rabbit MQ 会遵循策略,但是由于原来的队列里面已经有消息了,这些消息并未同步到实施策略后的镜像上,所以原来的队列并未删除,主队列也没有迁移至策略所指定的节点。Rabbit MQ 不默认采用同步的方式是因为:同步的方式会导致在同步期间系统对外是无响应的,这会降低系统的可用性,而不同步的时间通常会非常短暂,因为随着消息被消费,未同步的消息很快就消失了。两者相权,前者弊多利少,所以就采用非同步的方法。此时开启消费端程序,将未同步的消息消费掉,再看队列状态就已经完全符合策略要求了。
因此,本实验用于演示以上论述。
环境
实验室环境的 3 台 Rabbit MQ 服务器,已经配置好集群。
过程
- 查看集群时候正常运行
$rabbitmqctl cluster_status
Cluster status of node 'rabbit@TK-RABBITMQ1' ...
[{nodes,[{disc,['rabbit@TK-RABBITMQ1','rabbit@TK-RABBITMQ2',
'rabbit@TK-RABBITMQ3']}]},
{running_nodes,['rabbit@TK-RABBITMQ2','rabbit@TK-RABBITMQ3',
'rabbit@TK-RABBITMQ1']},
{cluster_name,<<"rabbit@TK-RABBITMQ1">>},
{partitions,[]},
{alarms,[{'rabbit@TK-RABBITMQ2',[]},
{'rabbit@TK-RABBITMQ3',[]},
{'rabbit@TK-RABBITMQ1',[]}]}]
2 清空所有的消息和策略 3 新建消息
使用控制台新建name为test.64_1 Node为rabbit@TK-RABBITMQ1的队列
使用控制台新建name为test.65_1 Node为rabbit@TK-RABBITMQ2的队列
使用控制台新建name为test.66_1 Node为rabbit@TK-RABBITMQ3的队列
使用客户端代码新建name为test.64_111 Node为rabbit@TK-RABBITMQ1的队列
使用客户端代码新建name为test.65_111 Node为rabbit@TK-RABBITMQ2的队列
使用客户端代码新建name为test.66_111 Node为rabbit@TK-RABBITMQ3的队列
注意:控制台和客户端新建队列区别是 客户端新建的队列有消息内容
4 查看队列信息
rabbitmqctl list_queues name policy pid slave_pids
呈现代码宏出错: 参数'firstline'的值无效
test.64_1 <rabbit@TK-RABBITMQ1.3.18018.20>
test.66_111 <rabbit@TK-RABBITMQ3.2.13477.170>
test.65_111 <rabbit@TK-RABBITMQ2.2.29265.20>
test.65_1 <rabbit@TK-RABBITMQ2.2.27457.20>
test.66_1 <rabbit@TK-RABBITMQ3.2.11610.170>
test.64_111 <rabbit@TK-RABBITMQ1.3.19994.20>
5 新建建立一个名为 test_policy 的策略,内容为:名称为 “test.” 开头的队列,镜像到集群里面的 TK-RABBITMQ2 和 TK-RABBITMQ3 节点。
rabbitmqctl set_policy test_policy "^test\." '{"ha-mode":"nodes","ha-params":["rabbit@TK-RABBITMQ2","rabbit@TK-RABBITMQ3"]}'
Setting policy "test_policy" for pattern "^test\\." to "{\"ha-mode\":\"nodes\",\"ha-params\":[\"rabbit@TK-RABBITMQ2\",\"rabbit@TK-RABBITMQ3\"]}" with priority "0" ...
6 再次查看队列信息
rabbitmqctl list_queues name policy pid slave_pids
test.64_1 test_policy <rabbit@TK-RABBITMQ2.2.2879.21> [<rabbit@TK-RABBITMQ3.2.19827.170>]
test.66_111 test_policy <rabbit@TK-RABBITMQ3.2.13477.170> [<rabbit@TK-RABBITMQ2.2.2861.21>]
test.65_111 test_policy <rabbit@TK-RABBITMQ2.2.29265.20> [<rabbit@TK-RABBITMQ3.2.19847.170>]
test.65_1 test_policy <rabbit@TK-RABBITMQ2.2.27457.20> [<rabbit@TK-RABBITMQ3.2.19840.170>]
test.66_1 test_policy <rabbit@TK-RABBITMQ3.2.11610.170> [<rabbit@TK-RABBITMQ2.2.2858.21>]
test.64_111 test_policy <rabbit@TK-RABBITMQ1.3.19994.20> [<rabbit@TK-RABBITMQ2.2.2873.21>, <rabbit@TK-RABBITMQ3.2.19842.170>]
此时发现队列名为 test.64_1 的 Node 改变为 rabbit@TK-RABBITMQ2 ,也就是没有消息内容的队列的 Node 变成有镜像的 Node。
7 把队列名为 test.64_111 的队列里面的消息消费完毕
8 再次查看队列信息
rabbitmqctl list_queues name policy pid slave_pids
test.64_1 test_policy <rabbit@TK-RABBITMQ2.2.2879.21> [<rabbit@TK-RABBITMQ3.2.19827.170>]
test.66_111 test_policy <rabbit@TK-RABBITMQ3.2.13477.170> [<rabbit@TK-RABBITMQ2.2.2861.21>]
test.65_111 test_policy <rabbit@TK-RABBITMQ2.2.29265.20> [<rabbit@TK-RABBITMQ3.2.19847.170>]
test.65_1 test_policy <rabbit@TK-RABBITMQ2.2.27457.20> [<rabbit@TK-RABBITMQ3.2.19840.170>]
test.66_1 test_policy <rabbit@TK-RABBITMQ3.2.11610.170> [<rabbit@TK-RABBITMQ2.2.2858.21>]
test.64_111 test_policy <rabbit@TK-RABBITMQ2.2.2873.21> [<rabbit@TK-RABBITMQ3.2.19842.170>]
此时发现队列名为 test.64_111 的 Node 变成 rabbit@TK-RABBITMQ2,也就是没有消息内容的队列的 Node 变成有镜像的 Node。
结论
本来想通过实验发现 程序 和 控制台 创建队列的区别,多次实验后发现并无不同,但是意外的验证了队列主从同步的细节。
更多实验可点击:Rabbitmq 实验