暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

RabbitMQ之机房迁移

不修边幅的创客 2020-09-09
1029

假设有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_app
rabbitmqctl 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镜像队列


如果我们不经过步骤四,而冒然去处理步骤5,下线老集群节点ABC,会发生exchanges和queues的master会漂移到DEF中到一个,并且是最早加入集群(ABC)的那一个,如果D是第一个加入的,那ABC上的master的镜像队列都漂移到D上,这样就造成D节点压力大,产生性能问题;
为什么会出现漂移? 因为rabbitmq在某一个master挂掉后,选择存活时间最长的节点作为挂掉节点exchanges和queues的主节点

如何避免? 通过如下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的hostname
rabbitmqctl 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的hostname
rabbitmqctl 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_app
rabbitmqctl reset
//如果不想使用了,就不用start了
rabbitmqctl start_app

如果有ABC有服务挂掉的:则执行如下命令(比如A挂了,那对A就得使用另外的命令):

//可以在好的节点B或者C上执行:
rabbitmqctl forget_cluster_node rabbit@A

使用上面的两种方法把老集群的节点下掉即可~

文章转载自不修边幅的创客,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论