天天看點

高速飛機上換引擎,MQ如何實作平滑遷移?

高速飛機上換引擎,MQ如何實作平滑遷移?

前幾天,楊紫瓊同學在知識星球提問,說公司要切換MQ,從一個舊的服務商更新為新的服務商,問有沒有什麼好方案。

這個需求估計還挺普遍的,這裡分享一些經驗。 一、MQ架構簡述

高速飛機上換引擎,MQ如何實作平滑遷移?

如上圖,使用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

如何平滑遷移,是今天要讨論的話題。 二、平滑遷移方案平滑遷移的目标是:不停服,平滑更新。 如果有很多主題,需要一個一個主題的遷移,每個主題的遷移,分為三個步驟。 步驟一:消費方雙向訂閱

高速飛機上換引擎,MQ如何實作平滑遷移?

如上圖所示,不妨設:

  • 粉色是舊MQ體系
  • 藍色是新MQ體系

平滑遷移最終目的,是“釋出-服務-訂閱”三層全由粉色更新為藍色。 第一步更新消費方,同一個主題,既要訂閱舊MQ,又要訂閱新MQ。 此時,“新服務-新訂閱”之間雖然有TCP連接配接,但“新釋出”沒有上線,實際上不會有消息發送過來(上圖虛線),消息仍走的是舊MQ(上圖實線)。 步驟二:生産方更新為新釋出

高速飛機上換引擎,MQ如何實作平滑遷移?

第二步更新生産方,由舊MQ釋出,更新為新MQ釋出。

 此時,“新釋出-新服務-新訂閱”之間會建立TCP連接配接,消息會轉移到新通道(上圖實線),“舊服務-舊訂閱”之間雖然有TCP連接配接,但實際不會有消息發送過來(上圖虛線)。 步驟三:消費方下線舊訂閱

高速飛機上換引擎,MQ如何實作平滑遷移?

第三步更新消費方,将舊訂閱下線,整個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更新為雙向訂閱。

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

 第二步:SendMsg更新為新釋出。

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

 第三步:RecvMsg下線舊訂閱。

 會發現,除了更新依賴新版的ShenJianMQ基礎元件,業務代碼不需要修改代碼。 不僅MQ,緩存與資料庫的用戶端,淺淺封裝一層也能實作業務代碼與基礎元件的解耦,在基礎組建替換,或者基礎組建更新的時候,業務代碼不需要更新。

畫外音:淺淺封裝一層之後,監控/告警/資料收集等工作都更容易統一實作了。 關于是使用開源,還是淺淺封裝,還是自研,

《基礎元件,究竟要不要自研?》

有更加詳盡的讨論。 關于MQ平滑遷移的問題,先聊這麼多,希望能解答楊紫瓊同學的問題。

本文轉自“架構師之路”公衆号,58沈劍提供。