
前幾天,楊紫瓊同學在知識星球提問,說公司要切換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。 此時,“新服務-新訂閱”之間雖然有TCP連接配接,但“新釋出”沒有上線,實際上不會有消息發送過來(上圖虛線),消息仍走的是舊MQ(上圖實線)。 步驟二:生産方更新為新釋出
第二步更新生産方,由舊MQ釋出,更新為新MQ釋出。
此時,“新釋出-新服務-新訂閱”之間會建立TCP連接配接,消息會轉移到新通道(上圖實線),“舊服務-舊訂閱”之間雖然有TCP連接配接,但實際不會有消息發送過來(上圖虛線)。 步驟三:消費方下線舊訂閱
第三步更新消費方,将舊訂閱下線,整個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沈劍提供。