49

高速飞机上换引擎,MQ如何实现平滑迁移?

 4 years ago
source link: https://www.tuicool.com/articles/fa6Vrye
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

VRzQraZ.jpg!web

前几天,杨紫琼同学在知识星球提问,说公司要切换MQ,从一个旧的服务商升级为新的服务商,问有没有什么好方案。

这个需求估计还挺普遍的,这里分享一些经验。

一、MQ架构简述

IjUZvuQ.png!web

如上图,使用MQ异步通信,一般分为 三层

消息发送方 :使用MQ客户端生成消息。

MQ-client:: SendMsg (topic, msg);

MQ服务 :中转消息。

消息接收方 :使用MQ客户端消费消息。

MQ-client:: RecvMsg (topic, msg, CALLBACK_FUNC);

这是一个典型的pub-sub架构,如果要替换MQ供应商,至少 三个地方要替换

  • 发送方mq-client

  • MQ-server

  • 接收方mq-client

如何平滑迁移,是今天要讨论的话题。

二、平滑迁移方案

平滑迁移的 目标 是: 不停服,平滑升级

如果有很多主题,需要一个一个主题的迁移,每个主题的迁移,分为 三个步骤

步骤一:消费方双向订阅

ZJziqyj.png!web

如上图所示,不妨设:

  • 粉色是旧MQ体系

  • 蓝色是新MQ体系

平滑迁移最终目的,是“发布-服务-订阅”三层全由粉色升级为蓝色。

第一步升级消费方,同一个主题,既要订阅旧MQ,又要订阅新MQ

此时,“新服务-新订阅”之间虽然有TCP连接,但“新发布”没有上线,实际上不会有消息发送过来(上图虚线),消息仍走的是旧MQ(上图实线)。

步骤二:生产方升级为新发布

aIVJnif.png!web

第二步升级生产方,由旧MQ发布,升级为新MQ发布

此时,“新发布-新服务-新订阅”之间会建立TCP连接,消息会转移到新通道(上图实线),“旧服务-旧订阅”之间虽然有TCP连接,但实际不会有消息发送过来(上图虚线)。

步骤三:消费方下线旧订阅

eIVNVbb.png!web

第三步升级消费方,将旧订阅下线,整个MQ的迁移完成

三、架构启示

MQ更换服务商,蚂蚁搬家,一步步平滑迁移,成本其实还挺高的。

之所以这么麻烦,不能统一升级,本质是 业务与底层基础设施细节 (即,具体使用哪个MQ)的 耦合 。如果公司在早期技术体系规划的时候,能够“浅浅的封装一层”,便能隔离“业务代码”与“底层基础设施细节”。

举个 更通俗的 例子。

假如 没有封装一层 ,业务代码是:

ActiveMQ -client::SendMsg(topic, msg);

ActiveMQ -client::RecvMsg(topic, msg, CALLBACK_FUNC);

即,业务方需要关心ActiveMQ,如果基础设施升级为RabbitMQ,业务代码需要升级。

假如 有一层浅浅的封装

ShenJianMQ::SendMsg(topic, msg){

ActiveMQ -client::SendMsg(topic,msg);

}

ShenJianMQ::RecvMsg(topic, msg,CALLBACK_FUNC)

ActiveMQ -client::RecvMsg(topic,msg, CALLBACK_FUNC);

}

业务方不需要关心底层是什么MQ ,而只需要依赖基础组件ShenJianMQ。

此时如果基础设施升级为RabbitMQ,只需要基础组件ShenJianMQ升级。

第一步: RecvMsg升级为双向订阅。

ShenJianMQ::RecvMsg(topic, msg,CALLBACK_FUNC)

ActiveMQ -client::RecvMsg(topic, msg, CALLBACK_FUNC);

RabbitMQ -client::RecvMsg(topic, msg, CALLBACK_FUNC);

}

第二步: SendMsg升级为新发布。

ShenJianMQ::SendMsg(topic, msg){

RabbitMQ -client::SendMsg(topic, msg);

}

第三步: RecvMsg下线旧订阅。

ShenJianMQ::RecvMsg(topic, msg,CALLBACK_FUNC)

RabbitMQ -client::RecvMsg(topic, msg, CALLBACK_FUNC);

}

会发现,除了升级依赖新版的ShenJianMQ基础组件, 业务代码不需要修改代码

不仅 MQ,缓存与数据库的客户端,浅浅封装一层

也能实现业务代码与基础组件的解耦,在基础组建替换,或者基础组建升级的时候,业务代码不需要升级。

画外音: 浅浅封装一层之后,监控/告警/数据收集等工作都更容易统一实现了。

关于是使用开源,还是浅浅封装,还是自研,《 基础组件,究竟要不要自研? 》有更加详尽的讨论。

关于MQ平滑迁移的问题,先聊这么多,希望能解答杨紫琼同学的问题。

me6f2mi.png!web

知识星球-刚开始玩


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK