天天看點

究竟什麼時候該使用MQ?

脫離業務的元件引入都是耍流氓。引入一個元件,最先該解答的問題是,此元件解決什麼問題。

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)異步傳回執行時間長;

知其然,知其是以然,希望大家有收獲。

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