MQ消息中間件

MQ是什麼?

MQ是Message Queue消息隊列的縮寫。消息隊列是一種應用程序對應用程序的通訊方法、應用程序經過寫和檢索入列隊的針對應用程序的數據(消息)來進行通訊,而不須要專用鏈接來連接它們。消息傳遞指的是程序之間經過在消息中發送數據進行通訊,而不是經過直接調用彼此來通訊,直接調用一般是用於諸如遠程過程調用的技術。排隊指的是應用程序經過隊列來通訊,隊列的使用除去了接收和發送應用程序同時執行的要求。數據庫

消息中間件的概況?安全

消息隊列技術是分佈式應用間交換信息的一種技術,消息隊列可駐留在內存或者磁盤上,隊列存儲消息直到它們被應用程序讀走,經過消息隊列,應用程序可獨立的執行---它們不須要知道彼此的位置。或者繼續執行前不須要等待接收程序接收此消息。微信

 

消息總線(Message Queue),後文稱MQ,是一種跨進程的通訊機制,用於上下游傳遞消息。網絡

 

在互聯網架構中,MQ是一種很是常見的上下游「邏輯解耦+物理解耦」的消息通訊服務。架構

使用了MQ以後,消息發送上游只須要依賴MQ,邏輯上和物理上都不用依賴其餘服務。異步

 

MQ相關的概念:

(1)消息Message分佈式

消息是MQ中最小的概念,本質上是一段數據,它能被一個或者多個應用程序所理解。是應用程序之間傳遞的信息載體、微信支付

(2)隊列Queue優化

a、本地隊列.net

本地隊列按照功能能劃分爲初始化隊列,傳輸隊列、目標隊列、死信隊列

    初始化隊列:用做消息觸發功能。

    傳輸隊列:只是暫存待傳的消息,條件許可的狀況下,經過管道將消息傳送到其餘的隊列管理器。

   目標隊列:是消息的目的地,能夠長期存放消息。

    死信隊列:當消息不能送到目標隊列,也再也不路由出去。則自動放入死信隊列保存。

b、別名隊列和遠程隊列

只是一個隊列的定義,用來指定遠程隊列管理器的隊列、使用了遠程隊列,程序就不須要知道目標隊列的位置、

c、模型隊列

模型隊列定義了一套本地隊列的屬性結合。一旦打開模型隊列,隊列管理器會按照這些屬性動態的建立出一個本地隊列。

(3)隊列管理器(Queue Manager)

隊列管理器時一個負責嚮應用程序提供消息服務的機構,若是把隊列管理器比做數據庫,那麼隊列就是其中的一張表、

(4)通道(Channel)

通道是兩個管理器之間的一種單向點對點的通訊鏈接,若須要雙向交流,能夠創建一對通道。

(5)監聽器(listener)

MQ產品特性

可靠性傳輸:這個特色是消息中間件的立足之本,對應用來講,只要成功把數據提交個消息中間件,那麼關於數據可靠傳輸的問題就由消息中間件來負責。

不重複傳輸 :不重複傳輸也就是斷點續傳的功能,特別適合在網絡不穩定的環境,節約網絡資源。

異步傳輸:接受信息雙方沒必要同時在線,具備脫機能力和安全性。

消息驅動:接到消息後主動通知消息接收方

支持事務:應用程序能夠把一些數據更新組合成一個工做單元,這些更新一般是邏輯相關的,爲了保障數據完整性,全部的更新必須同時成功或者同時失敗。

何時不使用消息總線

既然MQ是互聯網分層架構中的解耦利器,那全部通信都使用MQ豈不是很好?這是一個嚴重的誤區,調用與被調用的關係,是沒法被MQ取代的。

 

MQ的不足是:

1)系統更復雜,多了一個MQ組件

2)消息傳遞路徑更長,延時會增長

3)消息可靠性和重複性互爲矛盾,消息不丟不重難以同時保證

4)上游沒法知道下游的執行結果,這一點是很致命的

 

舉個栗子:用戶登陸場景,登陸頁面調用passport服務,passport服務的執行結果直接影響登陸結果,此處的「登陸頁面」與「passport服務」就必須使用調用關係,而不能使用MQ通訊。

 

不管如何,記住這個結論:調用方實時依賴執行結果的業務場景,請使用調用,而不是MQ。

 

何時使用MQ

【典型場景一:數據驅動的任務依賴】

 什麼是任務依賴,舉個栗子,互聯網公司常常在凌晨進行一些數據統計任務,這些任務之間有必定的依賴關係,好比:

1)task3須要使用task2的輸出做爲輸入

2)task2須要使用task1的輸出做爲輸入

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

對於這類需求,常見的實現方式是,使用cron人工排執行時間表:

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

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

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

 

這種方法的壞處是:

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

2)總任務的執行時間很長,老是要預留不少buffer,若是前置任務提早完成,後置任務不會提早開始

3)若是一個任務被多個任務依賴,這個任務將會稱爲關鍵路徑,排班表很難體現依賴關係,容易出錯

4)若是有一個任務的執行時間要調整,將會有多個任務的執行時間要調整

 

不管如何,採用「cron排班表」的方法,各任務耦合,誰用過誰痛誰知道(採用此法的請評論留言)

 

 

優化方案是,採用MQ解耦:

1)task1準時開始,結束後發一個「task1 done」的消息

2)task2訂閱「task1 done」的消息,收到消息後第一時間啓動執行,結束後發一個「task2 done」的消息

3)task3同理

 

採用MQ的優勢是:

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

2)依賴多個任務,被多個任務依賴都很好處理,只須要訂閱相關消息便可

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

 

須要特別說明的是,MQ只用來傳遞上游任務執行完成的消息,並不用於傳遞真正的輸入輸出數據。

 

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

上游須要關注執行結果時要用「調用」,上游不關注執行結果時,就可使用MQ了。

 

舉個栗子,58同城的不少下游須要關注「用戶發佈帖子」這個事件,好比招聘用戶發佈帖子後,招聘業務要獎勵58豆,房產用戶發佈帖子後,房產業務要送2個置頂,二手用戶發佈帖子後,二手業務要修改用戶統計數據。

 

對於這類需求,常見的實現方式是,使用調用關係:

帖子發佈服務執行完成以後,調用下游招聘業務、房產業務、二手業務,來完成消息的通知,但事實上,這個通知是否正常正確的執行,帖子發佈服務根本不關注。

 

這種方法的壞處是:

1)帖子發佈流程的執行時間增長了

2)下游服務當機,可能致使帖子發佈服務受影響,上下游邏輯+物理依賴嚴重

3)每當增長一個須要知道「帖子發佈成功」信息的下游,修改代碼的是帖子發佈服務,這一點是最噁心的,屬於架構設計中典型的依賴倒轉,誰用過誰痛誰知道(採用此法的請評論留言)

 

優化方案是,採用MQ解耦:

1)帖子發佈成功後,向MQ發一個消息

2)哪一個下游關注「帖子發佈成功」的消息,主動去MQ訂閱

 

採用MQ的優勢是:

1)上游執行時間短

2)上下游邏輯+物理解耦,除了與MQ有物理鏈接,模塊之間都不相互依賴

3)新增一個下游消息關注方,上游不須要修改任何代碼

 

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

 有時候上游須要關注執行結果,但執行結果時間很長(典型的是調用離線處理,或者跨公網調用),也常用回調網關+MQ來解耦。

 

舉個栗子,微信支付,跨公網調用微信的接口,執行時間會比較長,但調用方又很是關注執行結果,此時通常怎麼玩呢?

通常採用「回調網關+MQ」方案來解耦:

1)調用方直接跨公網調用微信接口

2)微信返回調用成功,此時並不表明返回成功

3)微信執行完成後,回調統一網關

4)網關將返回結果通知MQ

5)請求方收到結果通知

 

這裏須要注意的是,不該該由回調網關來調用上游來通知結果,若是是這樣的話,每次新增調用方,回調網關都須要修改代碼,仍然會反向依賴,使用回調網關+MQ的方案,新增任何對微信支付的調用,都不須要修改代碼啦。

 

總結

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

 

何時不使用MQ?

上游實時關注執行結果

 

何時使用MQ?

1)數據驅動的任務依賴

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

3)異步返回執行時間長

 

整理自:

https://blog.csdn.net/u011393781/article/details/52680686

https://blog.csdn.net/xybelieve1990/article/details/70313216/

相關文章
相關標籤/搜索