假设有3个节点(A、B、C)构建的RabbitMQ集群在老机房

本篇文章,我们的目的就是要在不丢失元数据和消息的情况下使用新机房的3个节点(D、E、F)代替老机房的老节点(A、B和C),从而实现机房之间的迁移.

1、新机房RabbitMQ Server部署
以前写过rabbitmq安装部署的过程,详情参考:RabbitMQ之安装部署.
每个server安装完以后,要强调以下几点:
1、新机房的集群节点(DEF)的.erlang.cookie内容要与老集群的一致;
使用源码安装方式在启动rabbitmq用户的用户目录下,如下图

rpm安装的在固定目录下: /var/lib/rabbitmq/.erlang.cookie

2、老机房ABC三台机器增加DEF的hosts绑定,新机房DEF每台机器互相绑定之外,还要增加ABC的绑定;
注意:
a、rabbitmq集群支持两种方式的hostname解析: 1、DNS方式 2、hosts绑定 ;
b、两种不能混用;(由于ABC使用的是hosts绑定,所以DEF只能使用hosts绑定,才能把DEF加入到ABC中)
c、使用DNS解析hostname时,记得在rabbitmq-env.conf增加:RABBITMQ_USE_LONGNAME=true参数;
3、rabbitmq.config的配置尽量与源集群保持一致;而rabbitmq-env.conf根据实际情况配置;
源码安装的配置路径,如下图:

rpm安装的配置路径,如下图:

特别注意:
由于ABC与DEF处于不同到机房,网段不同,要确保他们网络是打通的,如果网络不通,步骤2是做不了的
2、添加新节点DEF到老集群ABC中
分别在D、E和F节点上执行如下命令:
rabbitmqctl stop_apprabbitmqctl reset#此处要注意使用--ram把部分节点设置成内存节点,ABC任意节点都行rabbitmqctl join_cluster rabbit@${server A|B|C hostname}rabbitmqctl start_app
经过上面的步骤:就把DEF节点加入到老集群中,构建了一个大集群:

3、切换负载均衡服务
既然使用RabbitMQ服务,为了使各节点负载均匀,少不了负载均衡,不管你使用的是haproxy、vip等里面的哪一种,把对应的后端真实服务从ABC切换到DEF.笔者公司使用的:lvs + keepalived;
注意:
1、尽快完成迁移,因为是跨机房,节点个数为偶数,容易出现脑裂(后面会出一篇解决脑裂问题的文章);
2、经过在测试环境验证,切换完后,生产者不会报错,消费者会有报错,由于路由发生变化,指向ABC的channel被销毁,所以报错,但是不影响消费者继续指向DEF继续消费;消费端基于新的server创建channel,继续消费.报错信息如下:

3、如果ABC的网段与DEF不同,VIP服务会不支持,需要为DEF在对应网段搭建VIP服务.然后需要业务配合修改新的VIP地址,需要重启业务生效.
4、通过调整Policy方式切换master镜像队列

如何避免? 通过如下policy的priority(权重)参数控制:
1、管理员提前对所有的vhost进行划分,把exchanges和queues的主镜像均匀的分布到D、E、F 上;提前准备命令,如下参考:
#这个priority的权重一定要比现有policy大,不然没办法达到替换的目的rabbitmqctl set_policy -p /liuss --apply-to all --priority 100 liuss-all-policy "^" '{"ha-mode":"nodes","ha-params":["rabbit@vm-10-11-158-171"]}' 其中:假如vm-10-11-158-171为D的hostnamerabbitmqctl set_policy -p /zhou --apply-to all --priority 100 zhou-all-policy "^" '{"ha-mode":"nodes","ha-params":["rabbit@vm-10-11-158-172"]}' 其中:假如vm-10-11-158-172为E的hostnamerabbitmqctl set_policy -p /xmm --apply-to all --priority 100 xmm-all-policy "^" '{"ha-mode":"nodes","ha-params":["rabbit@vm-10-11-158-173"]}' 其中:假如vm-10-11-158-173为F的hostname
如上:通过--priority提升新建policy的权重,policy立刻生效,就会把部分原来在老节点的exchanges和queues转移到新节点.
2、删除时,要判断exchanges和queues消息是否同步,那如何判断同步呢? policy生效时,通过控制台的Queue的查看queue的状态即可,如果有正在迁移的,会有进度显示
3、待exchanges和queues同步完成后,删除刚刚创建的policy即可,原来的权重最大的policy就会生效;注意这时master已经转移;
4、这种强制提升新的master的操作会引起数据丢失(如果存在Unsynchronised mirrors队列) ,(造成不同步的队列很有可能是新的镜像队列,新的镜像队列不会主动同步主队列的老数据,它只关心新数据) , 如下官网介绍:

5、下线集群的ABC节点
在老机房的ABC节点上分别执行如下命令(假定ABC是存活的):
rabbitmqctl stop_apprabbitmqctl reset//如果不想使用了,就不用start了rabbitmqctl start_app
如果有ABC有服务挂掉的:则执行如下命令(比如A挂了,那对A就得使用另外的命令):
//可以在好的节点B或者C上执行:rabbitmqctl forget_cluster_node rabbit@A
使用上面的两种方法把老集群的节点下掉即可~




