自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

究竟什么時(shí)候該使用MQ?

開發(fā) 開發(fā)工具 前端
MQ,互聯(lián)網(wǎng)技術(shù)體系中一個(gè)常見組件,究竟什么時(shí)候不使用MQ,究竟什么時(shí)候使用MQ,MQ究竟適合什么場(chǎng)景,是今天要分享的內(nèi)容。

任何脫離業(yè)務(wù)的組件引入都是耍流氓。引入一個(gè)組件,最先該解答的問(wèn)題是,此組件解決什么問(wèn)題。

MQ,互聯(lián)網(wǎng)技術(shù)體系中一個(gè)常見組件,究竟什么時(shí)候不使用MQ,究竟什么時(shí)候使用MQ,MQ究竟適合什么場(chǎng)景,是今天要分享的內(nèi)容。

[[311801]]

MQ是什么?

消息總線(Message Queue),后文稱MQ,是一種跨進(jìn)程的通信機(jī)制,用于上下游傳遞消息。

畫外音:這兩個(gè)進(jìn)程,一般不在同一臺(tái)服務(wù)器上。

在互聯(lián)網(wǎng)架構(gòu)中,MQ經(jīng)常用做“上下游解耦”:

  • 消息發(fā)送方只依賴MQ,不關(guān)注消費(fèi)方是誰(shuí);
  • 消息消費(fèi)方也只依賴MQ,不關(guān)注發(fā)送方是誰(shuí);

畫外音:發(fā)送方與消費(fèi)方,邏輯上和物理上都不依賴彼此。

什么時(shí)候不使用MQ?

當(dāng)調(diào)用方需要關(guān)心消息執(zhí)行結(jié)果時(shí),通常不使用MQ,而使用RPC調(diào)用。

  1. ret = PassportService::userAuth(name, pass); 
  2. switch(ret){ 
  3.     case(YES) : return YesHTML(); 
  4.     case(NO) : return NoHTML(); 
  5.     case(JUMP) : return 304HTML(): 
  6.     default : return 500HTML(); 

如上例所示,上游調(diào)用Passport服務(wù),處理結(jié)果不同,業(yè)務(wù)會(huì)走不同的邏輯處理分支(登錄成功,登錄失敗,執(zhí)行錯(cuò)誤等),即“處理結(jié)果強(qiáng)依賴”,此時(shí)應(yīng)該使用RPC調(diào)用。

畫外音:絕大部分情況,應(yīng)該使用RPC。

此時(shí)如果強(qiáng)行使用MQ呢?

如果強(qiáng)行使用MQ通訊,調(diào)用方不能直接告之用戶登錄成功又或失敗,則要等待另一個(gè)MQ通知回調(diào)。這么玩,不但使得編碼復(fù)雜,還會(huì)引入消息丟失的風(fēng)險(xiǎn),中間多加入一層,多此一舉。

究竟什么時(shí)候使用MQ呢?

下面四類典型場(chǎng)景,應(yīng)該使用MQ。

典型場(chǎng)景一:數(shù)據(jù)驅(qū)動(dòng)的任務(wù)依賴

(1) 什么是任務(wù)依賴?

舉個(gè)栗子,互聯(lián)網(wǎng)公司經(jīng)常在凌晨進(jìn)行一些數(shù)據(jù)統(tǒng)計(jì)任務(wù),這些任務(wù)之間有一定的依賴關(guān)系,例如:

  • task3需要使用task2的輸出作為輸入;
  • task2需要使用task1的輸出作為輸入;

這樣的話,tast1, task2, task3之間就有任務(wù)依賴關(guān)系,必須task1先執(zhí)行,再task2執(zhí)行,載task3執(zhí)行。

(2) 對(duì)于這類需求,通常怎么實(shí)現(xiàn)呢?

常見的玩法是,crontab人工排執(zhí)行時(shí)間表。

如上圖,手動(dòng)設(shè)定如下:

  • task1,0:00執(zhí)行,經(jīng)驗(yàn)執(zhí)行時(shí)間為50分鐘;
  • task2,1:00執(zhí)行(為task1預(yù)留10分鐘buffer),經(jīng)驗(yàn)執(zhí)行時(shí)間也是50分鐘;
  • task3,2:00執(zhí)行(為task2預(yù)留10分鐘buffer);

crontab手動(dòng)排表有什么壞處呢?

  • 如果有一個(gè)任務(wù)執(zhí)行時(shí)間超過(guò)了預(yù)留buffer的時(shí)間,將會(huì)得到錯(cuò)誤的結(jié)果,因?yàn)楹笾萌蝿?wù)不清楚前置任務(wù)是否執(zhí)行成功,此時(shí)要手動(dòng)重跑任務(wù),還有可能要調(diào)整排班表;
  • 總?cè)蝿?wù)的執(zhí)行時(shí)間很長(zhǎng),總是要預(yù)留很多buffer,如果前置任務(wù)提前完成,后置任務(wù)不會(huì)提前開始;
  • 如果一個(gè)任務(wù)被多個(gè)任務(wù)依賴,這個(gè)任務(wù)將會(huì)稱為關(guān)鍵路徑,排班表很難體現(xiàn)依賴關(guān)系,容易出錯(cuò);
  • 如果有一個(gè)任務(wù)的執(zhí)行時(shí)間要調(diào)整,將會(huì)有多個(gè)任務(wù)的執(zhí)行時(shí)間要調(diào)整;

無(wú)論如何,采用“crontab排班表”的方法,各任務(wù)嚴(yán)重耦合,誰(shuí)用過(guò)誰(shuí)痛誰(shuí)知道。

畫外音:用過(guò)的,痛過(guò)的,請(qǐng)留言。

(3) 應(yīng)該如何優(yōu)化呢?

采用MQ解耦。

如上圖,任務(wù)之間通過(guò)MQ來(lái)傳遞“開始”與“結(jié)束”的通知:

  • task1準(zhǔn)時(shí)開始,結(jié)束后發(fā)一個(gè)“task1 done”的消息;
  • task2訂閱“task1 done”的消息,收到消息后第一時(shí)間啟動(dòng)執(zhí)行,結(jié)束后發(fā)一個(gè)“task2 done”的消息;
  • task3同理;

(4) 采用MQ有什么好處呢?

  • 不需要預(yù)留buffer,上游任務(wù)執(zhí)行完,下游任務(wù)總會(huì)在第一時(shí)間被執(zhí)行;
  • 依賴多個(gè)任務(wù),被多個(gè)任務(wù)依賴都很好處理,只需要訂閱相關(guān)消息即可;
  • 有任務(wù)執(zhí)行時(shí)間變化,下游任務(wù)都不需要調(diào)整執(zhí)行時(shí)間;

需要特別說(shuō)明的是,MQ只用來(lái)傳遞上游任務(wù)執(zhí)行完成的消息,并不用于傳遞真正的輸入輸出數(shù)據(jù)。

典型場(chǎng)景二:上游不關(guān)心執(zhí)行結(jié)果 

上游需要關(guān)注執(zhí)行結(jié)果時(shí)要用“RPC調(diào)用”,上游不關(guān)注執(zhí)行結(jié)果時(shí),使用MQ。

舉個(gè)栗子,58同城的很多下游需要關(guān)注“用戶發(fā)布帖子”這個(gè)事件,比如:

  • 招聘用戶發(fā)布帖子后,招聘業(yè)務(wù)要獎(jiǎng)勵(lì)58豆;
  • 房產(chǎn)用戶發(fā)布帖子后,房產(chǎn)業(yè)務(wù)要送2個(gè)置頂;
  • 二手用戶發(fā)布帖子后,二手業(yè)務(wù)要修改用戶統(tǒng)計(jì)數(shù)據(jù);

(1) 對(duì)于這類需求,可以采用什么方式實(shí)現(xiàn)呢?

比較無(wú)腦的,可以使用RPC調(diào)用來(lái)實(shí)現(xiàn):帖子發(fā)布服務(wù)執(zhí)行完成之后,調(diào)用下游招聘業(yè)務(wù)、房產(chǎn)業(yè)務(wù)、二手業(yè)務(wù),來(lái)完成消息的通知。

但事實(shí)上,這個(gè)通知是否正常正確的執(zhí)行,帖子發(fā)布服務(wù)根本不關(guān)注。

(2) 通過(guò)RPC來(lái)傳遞不需要知道處理結(jié)果的通知,有什么壞處呢?

  • 帖子發(fā)布流程的執(zhí)行時(shí)間增加了;
  • 下游服務(wù)當(dāng)機(jī),可能導(dǎo)致帖子發(fā)布服務(wù)受影響,上下游邏輯+物理依賴嚴(yán)重;
  • 每當(dāng)增加一個(gè)需要知道“帖子發(fā)布成功”信息的下游,修改代碼的是帖子發(fā)布服務(wù);

畫外音:這一點(diǎn)是最惡心的,屬于架構(gòu)設(shè)計(jì)中典型的反向依賴。

(3) 如何來(lái)進(jìn)行優(yōu)化呢?

采用MQ解耦,代替RPC。

如上圖所示:

  • 帖子發(fā)布成功后,向MQ發(fā)一個(gè)消息;
  • 哪個(gè)下游關(guān)注“帖子發(fā)布成功”的消息,主動(dòng)去MQ訂閱;

(4) 如此一來(lái),有什么好處呢?

  • 上游執(zhí)行時(shí)間短;
  • 上下游邏輯+物理解耦,除了與MQ有物理連接,模塊之間都不相互依賴;
  • 新增一個(gè)下游消息關(guān)注方,上游不需要修改任何代碼。

典型場(chǎng)景三:上游關(guān)注執(zhí)行結(jié)果,但執(zhí)行時(shí)間很長(zhǎng)

有時(shí)候上游需要關(guān)注執(zhí)行結(jié)果,但執(zhí)行結(jié)果時(shí)間很長(zhǎng)(典型的是調(diào)用離線處理,或者跨公網(wǎng)調(diào)用),也經(jīng)常使用回調(diào)網(wǎng)關(guān)+MQ來(lái)解耦。

舉個(gè)栗子,微信支付,跨公網(wǎng)調(diào)用微信的接口,執(zhí)行時(shí)間會(huì)比較長(zhǎng),但調(diào)用方又非常關(guān)注執(zhí)行結(jié)果,此時(shí)一般怎么玩呢?

一般采用“回調(diào)網(wǎng)關(guān)+MQ”方案來(lái)解耦:

  • 調(diào)用方直接跨公網(wǎng)調(diào)用微信接口;
  • 微信返回調(diào)用成功,此時(shí)并不代表返回成功;
  • 微信執(zhí)行完成后,回調(diào)統(tǒng)一網(wǎng)關(guān);
  • 網(wǎng)關(guān)將返回結(jié)果通知MQ;
  • 請(qǐng)求方收到結(jié)果通知;

這里需要注意的是,不應(yīng)該由回調(diào)網(wǎng)關(guān)來(lái)RPC通知上游來(lái)通知結(jié)果,如果是這樣的話,每次新增調(diào)用方,回調(diào)網(wǎng)關(guān)都需要修改代碼,仍然會(huì)反向依賴,使用回調(diào)網(wǎng)關(guān)+MQ的方案,新增任何對(duì)微信支付的調(diào)用,都不需要修改代碼。

結(jié)尾總結(jié)

MQ是一個(gè)互聯(lián)網(wǎng)架構(gòu)中常見的解耦利器。

什么時(shí)候不使用MQ?

上游實(shí)時(shí)關(guān)注執(zhí)行結(jié)果,通常采用RPC。

什么時(shí)候使用MQ?

  • 數(shù)據(jù)驅(qū)動(dòng)的任務(wù)依賴;
  • 上游不關(guān)心多下游執(zhí)行結(jié)果;
  • 異步返回執(zhí)行時(shí)間長(zhǎng);

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

【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文

 

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專欄
相關(guān)推薦

2017-04-05 21:43:08

MQ互聯(lián)網(wǎng)架構(gòu)

2025-02-28 09:04:08

2014-09-23 10:16:03

程序員

2022-05-19 10:27:34

機(jī)器學(xué)習(xí)人工智能

2017-06-28 15:06:51

PythonLambda函數(shù)

2014-09-17 10:57:22

802.11acWLAN

2013-04-25 10:28:38

大數(shù)據(jù)云服務(wù)

2012-07-26 10:27:31

PHP

2020-05-12 11:25:50

MySQLES數(shù)據(jù)庫(kù)

2017-05-15 09:55:07

2015-07-08 15:55:01

NSStringcopystrong

2013-09-29 17:13:59

PowerShell工作流

2013-11-28 16:03:24

2012-09-24 10:20:39

JavaScriptJS

2009-06-19 16:29:47

EJBXML

2010-11-09 13:58:03

SQL Server鎖

2020-07-24 09:20:44

MapObject前端

2024-08-05 01:22:16

2020-06-17 10:35:16

機(jī)器學(xué)習(xí)AI人工智能

2020-09-06 09:57:34

Node框架開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)