您當前的位置:首頁 > 攝影

究竟什麼時候該使用MQ?

作者:由 Java物聯網架構師 發表于 攝影時間:2022-11-17

任何脫離業務的元件引入都是耍流氓。

引入一個元件,最先該解答的問題是,此元件解決什麼問題。

MQ,網際網路技術體系中一個常見元件

,究竟什麼時候不使用MQ,究竟什麼時候使用MQ,MQ究竟適合什麼場景,是今天要分享的內容。

MQ是什麼?

訊息匯流排(Message Queue),後文稱MQ,是一種跨程序的通訊機制,用於上下游傳遞訊息。

畫外音:這兩個程序,一般不在同一臺伺服器上。

究竟什麼時候該使用MQ?

在網際網路架構中,MQ經常用做“上下游解耦”:

(1)訊息傳送方只依賴MQ,不關注消費方是誰;

(2)訊息消費方也只依賴MQ,不關注傳送方是誰;

什麼時候不使用MQ?

當呼叫方需要關心訊息執行結果時,通常不使用MQ,而使用RPC呼叫。

究竟什麼時候該使用MQ?

ret = PassportService::userAuth(name, pass);

switch(ret){

case(YES) : return YesHTML();

case(NO) : return NoHTML();

case(JUMP) : return 304HTML():

default : return 500HTML();

}

如上例所示,上游呼叫Passport服務,處理結果不同,業務會走不同的邏輯處理分支(登入成功,登入失敗,執行錯誤等),即“處理結果強依賴”,此時應該使用RPC呼叫。

畫外音:絕大部分情況,應該使用RPC。

此時如果強行使用MQ呢?

究竟什麼時候該使用MQ?

如果強行使用MQ通訊,呼叫方不能直接告知使用者登入成功又或失敗,則要等待另一個MQ通知回撥。這麼玩,不但使得編碼複雜,還會引入訊息丟失的風險,中間多加入一層,多此一舉。

究竟什麼時候使用MQ呢?

下面四類典型場景,應該使用MQ。

典型場景一:資料驅動的任務依賴

什麼是任務依賴?

舉個例子,網際網路公司經常在凌晨進行一些資料統計任務,這些任務之間有一定的依賴關係,例如:

(1)task3需要使用task2的輸出作為輸入;

(2)task2需要使用task1的輸出作為輸入;

這樣的話,tast1, task2, task3之間就有任務依賴關係,必須task1先執行,再task2執行,載task3執行。

對於這類需求,通常怎麼實現呢?

常見的玩法是,crontab人工排執行時間表。

究竟什麼時候該使用MQ?

如上圖,手動設定如下:

(1)task1,0:00執行,經驗執行時間為50分鐘;

(2)task2,1:00執行(為task1預留10分鐘buffer),經驗執行時間也是50分鐘;

(3)task3,2:00執行(為task2預留10分鐘buffer);

crontab手動排表有什麼壞處呢?

(1)如果有一個任務執行時間超過了預留buffer的時間,將會得到錯誤的結果,因為後置任務不清楚前置任務是否執行成功,此時要手動重跑任務,還有可能要調整排班表;

(2)總任務的執行時間很長,總是要預留很多buffer,如果前置任務提前完成,後置任務不會提前開始;

(3)如果一個任務被多個任務依賴,這個任務將會成為關鍵路徑,排班表很難體現依賴關係,容易出錯;

(4)如果有一個任務的執行時間要調整,將會有多個任務的執行時間要調整;

無論如何,採用“crontab排班表”的方法,各任務嚴重耦合,誰用過誰痛誰知道。

畫外音:用過的,痛過的,請留言。

應該如何最佳化呢?

採用MQ解耦。

究竟什麼時候該使用MQ?

如上圖,任務之間透過MQ來傳遞“開始”與“結束”的通知:

(1)task1準時開始,結束後發一個“task1 done”的訊息;

(2)task2訂閱“task1 done”的訊息,收到訊息後第一時間啟動執行,結束後發一個“task2 done”的訊息;

(3)task3同理;

採用MQ有什麼好處呢?

(1)不需要預留buffer,上游任務執行完,下游任務總會在第一時間被執行;

(2)依賴多個任務,被多個任務依賴都很好處理,只需要訂閱相關訊息即可;

(3)有任務執行時間變化,下游任務都不需要調整執行時間;

需要特別說明的是,MQ只用來傳遞上游任務執行完成的訊息,

並不用於傳遞真正的輸入輸出資料

典型場景二:上游不關心執行結果

上游需要關注執行結果時要用“RPC呼叫”,上游不關注執行結果時,使用MQ。

舉個栗子,58同城的很多下游需要關注“使用者釋出帖子”這個事件,比如:

(1)招聘使用者釋出帖子後,招聘業務要獎勵58豆;

(2)房產使用者釋出帖子後,房產業務要送2個置頂;

(3)二手使用者釋出帖子後,二手業務要修改使用者統計資料;

對於這類需求,可以採用什麼方式實現呢?

究竟什麼時候該使用MQ?

比較無腦的,可以使用RPC呼叫來實現:

帖子釋出服務執行完成之後,呼叫下游招聘業務、房產業務、二手業務,來完成訊息的通知。

但事實上,這個通知是否正常正確的執行,帖子釋出服務根本不關注。

透過RPC來傳遞不需要知道處理結果的通知,有什麼壞處呢?

(1)帖子釋出流程的執行時間增加了;

(2)下游服務當機,可能導致帖子釋出服務受影響,上下游邏輯+物理依賴嚴重;

(3)每當增加一個需要知道“帖子釋出成功”資訊的下游,修改程式碼的是帖子釋出服務;

畫外音:這一點是最噁心的,屬於架構設計中典型的反向依賴。

如何來進行最佳化呢?

採用MQ解耦,代替RPC。

究竟什麼時候該使用MQ?

如上圖所示:

(1)帖子釋出成功後,向MQ發一個訊息;

(2)哪個下游關注“帖子釋出成功”的訊息,主動去MQ訂閱;

如此一來,有什麼好處呢?

(1)上游執行時間短;

(2)上下游邏輯+物理解耦,除了與MQ有物理連線,模組之間都不相互依賴;

(3)新增一個下游訊息關注方,上游不需要修改任何程式碼;

典型場景三:上游關注執行結果,但執行時間很長

有時候上游需要關注執行結果,但執行結果時間很長(典型的是呼叫離線處理,或者跨公網呼叫),也經常使用回撥閘道器+MQ來解耦。

舉個栗子,微信支付,跨公網呼叫微信的介面,執行時間會比較長,

但呼叫方又非常關注執行結果,此時一般怎麼玩呢?

究竟什麼時候該使用MQ?

一般採用“回撥閘道器+MQ”方案來解耦:

(1)呼叫方直接跨公網呼叫微信介面;

(2)微信返回呼叫成功,此時並不代表返回成功;

(3)微信執行完成後,回撥統一閘道器;

(4)閘道器將返回結果通知MQ;

(5)請求方收到結果通知;

這裡需要注意的是,不應該由回撥閘道器來RPC通知上游來通知結果,如果是這樣的話,每次新增呼叫方,回撥閘道器都需要修改程式碼,仍然會反向依賴,使用回撥閘道器+MQ的方案,新增任何對微信支付的呼叫,都不需要修改程式碼。

結尾總結

MQ是一個網際網路架構中常見的解耦利器。

什麼時候不使用MQ?

上游實時關注執行結果,通常採用RPC。

什麼時候使用MQ?

(1)資料驅動的任務依賴;

(2)上游不關心多下游執行結果;

(3)非同步返回執行時間長;

標簽: MQ  執行  任務  呼叫  RPC