初識MQ

MQ後端

做爲金融企業對公衆提供服務必定要保證其可用性,儘可能作到更多個9(通常SLA中描述的高可用性99.99%,中的9越多表明整年服務可用時間越長服務更可靠,停機時間越短),隨着軟件系統的複雜度愈來愈高,故障是不可避免的。這就須要企業實現總體的彈性架構(Resilient Architecture),爲應對故障而設計。緩存

由於是同步請求,常由於執行方失敗、超時等因素而影響最終用戶體驗,並且不少故障是沒法完全消除的。並且RPC和RMI調用須要服務的消費方和服務的提供方同時在線,而且雙方須要經過某種機制確認彼此的調用關係,由於存在這些弊端,就致使了面向消息的中間件(MOM)的產生,經過在企業架構中引入消息中間件,確保在故障發生時,受此影響的系統部分在一個很小的範圍內。消息中間件就是在分佈式系統中間引入一個透明的中間層,隔離服務的提供方和消費方。服務器

2 爲何要引入MQ網絡

2.1何爲MQ多線程

消息隊列(MQ)是一種不一樣應用程序之間(跨進程)的通訊方法,用於上下游應用程序之間傳遞消息。咱們拆分來看:架構

消息:應用程序經過寫入和檢索出入列隊的數據(消息)來通訊。併發

隊列:除去了接收和發送應用程序同時執行的要求。負載均衡

這樣就實現了上游與下游之間的解耦,上游向MQ發送消息,下游從MQ接收消息,上游下游互不依賴,它們只依賴MQ。由於有隊列的存在,MQ可在上下游之間進行緩衝,把上游信息先緩存起來,下游根據本身的能力從MQ中拉去信息,起到削峯的做用。異步

2.2 使用MQ帶來的好處分佈式

2.2.1 解耦

 什麼是耦合

高內聚低耦合,是軟件工程中的概念,這裏的低耦合是指各個組件之間,儘量相互獨立。通俗一點的理解就是,增長模塊間調用透明化,最高的透明度就是不用知道彼此的存在,所以減小接口的複雜性、規範調用的方式及傳遞的信息,下降產品各模塊的依賴,提升重用程度。

如何解耦

在企業總體架構中解耦,主要設計兩個方面:一是簡化減小交互,二是增長一箇中間層實現兩方的隔離,MQ就是其中的中間層(以下圖所示)。

 

引入MQ後生產者和消費者沒必要知道彼此的存在也沒必要同時在線,主要交互流程以下:

1) 生產者負責:生產消息並經過SDK或API調用發送給MQ(同步發送或者異步發送);

2) MQ負責:接收消息,並持久化消息到消息存儲(同步或異步存儲消息);

3) 生產者接收來自MQ的響應(消息發送狀態或異常);

4) 消費者訂閱消息後,接收來自MQ的消息;

5) 消費者執行消息對應的後續業務操做;

6) 對消費結果進行確認(消費成功、失敗、異常等)。

2.2.2 削峯填谷

因爲系統閒忙分佈不均,QPS常相差幾十倍甚至更高,特別是在遇到營銷活動時,瞬間流量極可能超事後端系統的承載能力,這就要考慮經過消息中間件來緩衝,MQ客戶端實例根據本身的處理能力從MQ服務器拉取消息,以此來減輕或消除後端系統的瓶頸。

 

 

2.2.3 異構集成

因爲各類緣由,咱們在企業信息化建設過程當中,都會面臨軟件產品來自不一樣的廠家只解決某特定領域的問題,這些產品由於封閉的架構沒法對外提供服務或缺乏核心開發而沒法作大的改造,這就形成了彼此之間很難集成。經過引入MQ能夠部分解決該問題,只須要在某個環節生產一條消息,或者根據消息作出具體的響應,只需與MQ對接,沒必要與其餘系統作一對一的對接。

2.2.4異步隔離

爲了提供金融服務的總體彈性,須要隔離內部、外部系統間的依賴。如支付通知分爲兩種,一種是同步通知,這時API調用會由於網絡故障而超時,由於服務提供方處理能力限制而得不到及時響應……等多種因素影響,另外一種是異步通知,在必定時效範圍內最終通知到便可,從而提供提升最終用戶的體驗和交易成功率,提升業務的總體生產率。

3.常見產品特性比較

4.MQ的兩種模式:點對點、發佈/訂閱

點對點模式:Queue,不可重複消費

生產者發送一條消息到queue,一個queue能夠有不少消費者,可是一個消息只能被一個消費者接受,當沒有消費者可用時,這個消息會被保存在queue中直到有一個可用的消費者;消息被消費之後,queue中再也不有存儲,因此消息消費者不可能消費到已經被消費的消息。因此Queue實現了一個可靠的負載均衡。

 

 

發佈/訂閱模式:Topic,能夠重複消費

發佈/訂閱模式涉及三個角色:發佈者、訂閱者、消費者

訂閱者:是成爲消費者的前提,訂閱是向發佈者說明本身是個消費者的過程。簡單來講,發佈者發送到topic的消息,只有訂閱了topic的訂閱者才能成爲消費者,纔會接收到消息。

Topic: 發佈/訂閱模式中的topic實現了發佈和訂閱,當發佈一個消息,全部訂閱這個topic的服務都能獲得這個消息,因此從1到N個訂閱者都能獲得這個消息的拷貝。

整個實現上分三個步驟:

一、  初始化發佈者、訂閱者。

二、  訂閱者註冊到發佈者

三、  發佈者依次向訂閱者發佈消息。

點對點模式和發佈/訂閱模式的結合:

發佈訂閱模式下,當發佈者的消息量很大時,單個訂閱者的處理能力很難知足系統要求。在實際應用場景中,通常是由多個訂閱者節點組成一個訂閱組來消費topic信息,即分組訂閱,每一個消息只會由一個訂閱組中的某一個訂閱者來消費, 相似於點對點模式。這種模式下很容易就能實現對消費能力的線性擴展。

4、MQ主要應用場景:

主要針對如下特徵可採用MQ

一、解耦

以貸款扣款爲例: 訂單系統 –> MQ -> 結算系統

訂單系統在生成用戶訂單後將消息拋送至MQ後當即返回,而後由結算系統去消費該MQ中的消息,進行用戶帳戶金額的扣減。這樣就將訂單生成系統和結算系統就好了解耦,訂單系統只需關注建立訂單,無需等待後續流程的執行結果,這樣能夠減少訂單系統的壓力,最大可能的提升系統響應速度,進而提高訂單量,而結算系統則只需關心帳戶金額扣減,保證帳戶金額的一致性便可。

二、削峯填谷

在每逢大促時,訂單系統就會迎來數量高峯,在短期內會生成大量的訂單,這勢必會給結算系統帶來壓力,在短期內升高服務器的利用率,甚至滿載,從而達到系統瓶頸。而在訂單低谷期訂單量比較小,結算系統服務器又會長時間處於空閒狀態。

此類問題能夠經過MQ的方式來解決。訂單系統將訂單消息拋送至MQ隊列後,結算系統會經過消費端拉取消息的方式來處理訂單消息,拉取的速度可由結算系統根據當前自身服務器的狀況進行控制,這樣就能夠避開因爲大促帶來的訂單瞬時高峯,使結算流量趨於平穩,保證告終算系統的穩定性。

三、最終一致性

訂單系統:建立成功訂單、發送成功通知到MQ,兩個操做能夠當作一個事務。

 

當一次發送MQ失敗以後,能夠結合定時任務進行補償,這樣能夠保證生成訂單的結果能夠落地到mq的存儲中。一樣結算系統消費端依靠MQ重試機制一直髮送消息,直到消費端最終確認扣款業務成功處理完成。這樣咱們經過MQ實現了最終一致性。

 

5、優缺點

MQ對應的優勢是:

一、高併發

在高併發分佈式環境下,因爲來不及同步處理,請求每每發生堵塞,影響系統性能;而異步處理請求,能夠緩解系統的壓力。

二、鬆耦合

任何一個應用對MQ的調用不依賴於任何其它應用,沒有任何依賴或者時序要求,應用依賴於MQ的能力保證消息傳遞。(應用發送消息到MQ以後並不關心消息如何或者何時被傳遞。一樣的消息的接收者也不關心消息從哪裏或者如何到來。在不一樣的環境中這樣作的好處是容許客戶端使用不一樣的語言編寫甚至使用不一樣的線路協議。MQ做爲中間人存在,容許不一樣環境的集成和異步交互。)

MQ的不足是:

一、多了一個MQ組件,使消息系統更加複雜 。

二、消息傳遞路徑更長,延時會增長 。

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

四、上游沒法知道下游的執行結果。

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

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

 

6.問題總結

1、消息亂序

有些業務場景,好比購買流程,下單和扣款兩個操做是有前後順序的。

Topic1: 隊列1

              隊列2

              隊列3

              ……

Topic2:   隊列1

              隊列2

              ……

生產者發出topic+消息體, 根據匹配topic能夠判斷出應該把消息丟到哪一個隊列裏。每一個隊列對應惟一topic,同一topic可能對應多個隊列。也就是同一種topic的消息可能進入到不一樣隊列裏,即使在同一個隊列裏的消息一般也是多線程處理的,因此沒法保證消息的順序。

要實現嚴格的順序消息,簡單且可行的辦法就是:保證生產者 - MQ - 消費者是一對一對一的關係。好比同一個topic下只有一個隊列,且隊列是單線程處理的。但存在問題:一、並行度不夠,影響整個系統性能。二、發生異常時(如消費端出現問題),會致使整個處理流程阻塞,須要花費更多時間解決問題。

PS:目前市場上不少應用都是不關心消息是否亂序的。而針對大部分業務場景也是沒必要要求消息順序的。

針對必需要保證順序的業務,能夠設置業務id,同一個業務的一組消息設置同一個id,丟入同一個隊列中,而且單線程處理。

 

2、消息重複

因爲網絡延遲等容易引入消息重複的問題。如今一般的處理方法是不解決。可是不解決可能存在消費端收到兩條同樣的消息。解決這個問題,一般兩種方法:

A、冪等性

冪等性:某個函數或者某個接口使用相同參數調用一次或者無限次,其形成的後果是同樣的。

好比在系統中,調用方A調用系統B的接口進行用戶的扣費操做時,因爲網絡不穩定,A重試了N次該請求,那麼無論B是否接收到多少次請求,都應該保證只會扣除該用戶一次費用。

例如:對於訂單扣費行爲,系統會生成惟一全局的一個流水號用來標識同一個業務流程,多個相同業務流程的流水號不重複。服務器1處理了流水號1的扣費行爲後,再有流水號1的扣款消息到達其餘服務器時,不管執行幾回扣款行爲,最終結果都是隻扣款1次。

B、日誌表

在後臺維護一張表從而達到去重的目的。好比每條消息設置惟一的消息id,若發送成功則記錄在日誌表中,新消息到達時,查看消息是否已經在日誌表中,若存在則再也不處理。

PS:MQ實現去重邏輯,必定程度上會影響消息系統的性能,因此目前不少去重邏輯是由上游業務方來保證。(MQ+上游雙重保證)

 

3、消息重試:生產者端重試、消費者端重試

重點說下消費者端重試,消費結果兩種:一、成功;二、失敗重試。消費者必須返回其中一種結果。

消費者端的失敗,分爲2種狀況,一個是exception,一個是timeout。

 

Exception: 消息正常的到了消費者,結果消費者發生異常,處理失敗了。

處理方法:mq把失敗的消息丟到重試隊列中,重試隊列通常會有重試次數限制,若超過該次數仍未消費成功,通常會有兩種處理:一、丟棄該消息。(經常使用)二、再也不重試,且存儲該消息,並使用另一種方式消費。

 

Timeout:好比因爲網絡緣由致使消息沒有從MQ到達消費者上。

處理方法:丟到重試隊列中不斷的嘗試發送這條消息,直至發送成功爲止!(一般咱們會設置重試上限)

相關文章
相關標籤/搜索