高速飛機(jī)上換引擎,MQ如何實(shí)現(xiàn)平滑遷移?

前幾天,楊紫瓊同學(xué)在知識(shí)星球提問(wèn),說(shuō)公司要切換MQ,從一個(gè)舊的服務(wù)商升級(jí)為新的服務(wù)商,問(wèn)有沒(méi)有什么好方案。
這個(gè)需求估計(jì)還挺普遍的,這里分享一些經(jīng)驗(yàn)。
一、MQ架構(gòu)簡(jiǎn)述
如上圖,使用MQ異步通信,一般分為三層:消息發(fā)送方:使用MQ客戶(hù)端生成消息。
- MQ-client::SendMsg(topic, msg);
MQ服務(wù):中轉(zhuǎn)消息。 消息接收方:使用MQ客戶(hù)端消費(fèi)消息。
- MQ-client::RecvMsg(topic, msg, CALLBACK_FUNC);
這是一個(gè)典型的pub-sub架構(gòu),如果要替換MQ供應(yīng)商,至少三個(gè)地方要替換:
- 發(fā)送方mq-client
- MQ-server
- 接收方mq-client
如何平滑遷移,是今天要討論的話題。
二、平滑遷移方案
平滑遷移的目標(biāo)是:不停服,平滑升級(jí)。 如果有很多主題,需要一個(gè)一個(gè)主題的遷移,每個(gè)主題的遷移,分為三個(gè)步驟。
步驟一:消費(fèi)方雙向訂閱
如上圖所示,不妨設(shè):
- 粉色是舊MQ體系
- 藍(lán)色是新MQ體系
平滑遷移最終目的,是“發(fā)布-服務(wù)-訂閱”三層全由粉色升級(jí)為藍(lán)色。 第一步升級(jí)消費(fèi)方,同一個(gè)主題,既要訂閱舊MQ,又要訂閱新MQ。
此時(shí),“新服務(wù)-新訂閱”之間雖然有TCP連接,但“新發(fā)布”沒(méi)有上線,實(shí)際上不會(huì)有消息發(fā)送過(guò)來(lái)(上圖虛線),消息仍走的是舊MQ(上圖實(shí)線)。
步驟二:生產(chǎn)方升級(jí)為新發(fā)布
第二步升級(jí)生產(chǎn)方,由舊MQ發(fā)布,升級(jí)為新MQ發(fā)布。
此時(shí),“新發(fā)布-新服務(wù)-新訂閱”之間會(huì)建立TCP連接,消息會(huì)轉(zhuǎn)移到新通道(上圖實(shí)線),“舊服務(wù)-舊訂閱”之間雖然有TCP連接,但實(shí)際不會(huì)有消息發(fā)送過(guò)來(lái)(上圖虛線)。
步驟三:消費(fèi)方下線舊訂閱
第三步升級(jí)消費(fèi)方,將舊訂閱下線,整個(gè)MQ的遷移完成。
三、架構(gòu)啟示
MQ更換服務(wù)商,螞蟻搬家,一步步平滑遷移,成本其實(shí)還挺高的。
之所以這么麻煩,不能統(tǒng)一升級(jí),本質(zhì)是業(yè)務(wù)與底層基礎(chǔ)設(shè)施細(xì)節(jié)(即,具體使用哪個(gè)MQ)的耦合。如果公司在早期技術(shù)體系規(guī)劃的時(shí)候,能夠“淺淺的封裝一層”,便能隔離“業(yè)務(wù)代碼”與“底層基礎(chǔ)設(shè)施細(xì)節(jié)”。
舉個(gè)更通俗的例子。
假如沒(méi)有封裝一層,業(yè)務(wù)代碼是:
- ActiveMQ-client::SendMsg(topic, msg);
- ActiveMQ-client::RecvMsg(topic, msg, CALLBACK_FUNC);
即,業(yè)務(wù)方需要關(guān)心ActiveMQ,如果基礎(chǔ)設(shè)施升級(jí)為RabbitMQ,業(yè)務(wù)代碼需要升級(jí)。 假如有一層淺淺的封裝:
- ShenJianMQ::SendMsg(topic, msg){
- ActiveMQ-client::SendMsg(topic,msg);
- }
- ShenJianMQ::RecvMsg(topic, msg,CALLBACK_FUNC)
- ActiveMQ-client::RecvMsg(topic,msg, CALLBACK_FUNC);
- }
業(yè)務(wù)方不需要關(guān)心底層是什么MQ,而只需要依賴(lài)基礎(chǔ)組件ShenJianMQ。
此時(shí)如果基礎(chǔ)設(shè)施升級(jí)為RabbitMQ,只需要基礎(chǔ)組件ShenJianMQ升級(jí)。
第一步:RecvMsg升級(jí)為雙向訂閱。
- ShenJianMQ::RecvMsg(topic, msg,CALLBACK_FUNC)
- ActiveMQ-client::RecvMsg(topic, msg, CALLBACK_FUNC);
- RabbitMQ-client::RecvMsg(topic, msg, CALLBACK_FUNC);
- }
第二步:SendMsg升級(jí)為新發(fā)布。
- ShenJianMQ::SendMsg(topic, msg){
- RabbitMQ-client::SendMsg(topic, msg);
- }
第三步:RecvMsg下線舊訂閱。
- ShenJianMQ::RecvMsg(topic, msg,CALLBACK_FUNC)
- RabbitMQ-client::RecvMsg(topic, msg, CALLBACK_FUNC);
- }
會(huì)發(fā)現(xiàn),除了升級(jí)依賴(lài)新版的ShenJianMQ基礎(chǔ)組件,業(yè)務(wù)代碼不需要修改代碼。
不僅MQ,緩存與數(shù)據(jù)庫(kù)的客戶(hù)端,淺淺封裝一層也能實(shí)現(xiàn)業(yè)務(wù)代碼與基礎(chǔ)組件的解耦,在基礎(chǔ)組建替換,或者基礎(chǔ)組建升級(jí)的時(shí)候,業(yè)務(wù)代碼不需要升級(jí)。
畫(huà)外音:淺淺封裝一層之后,監(jiān)控/告警/數(shù)據(jù)收集等工作都更容易統(tǒng)一實(shí)現(xiàn)了。
關(guān)于MQ平滑遷移的問(wèn)題,先聊這么多,希望能解答楊紫瓊同學(xué)的問(wèn)題。
【本文為51CTO專(zhuān)欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】