RabbitMQ消息中間件的理解

是什麼:微服務之間的消息通訊方式
常見的消息中間件:
  ActiveMQ:基於JMS
  RabbitMQ:基於AMQP協議,erlang語言開發,穩定性好
  RocketMQ:基於JMS,阿里巴巴產品,目前交由Apache基金會
  Kafka:分佈式消息系統,高吞吐量
MQ實現方式:AMQP (只是一種協議因此支持跨平臺)與jms(必須是java語言) 
好處:(轉載---爲何使用MQ說明:  http://www.javashuo.com/article/p-rweywryn-cm.html )
    一、解耦,消費方只須要訂閱讀取消息便可
    二、靈活性,峯值處理好
    三、MQ的處理異步的,這樣就提高了系統的處理性能。
    四、可恢復性
    五、順序保證
    六、緩衝能力,消息中間件像是一個巨大的蓄水池,將高峯期大量的請求存儲下來慢慢交給後臺進行處理,對於秒殺業務來講尤其重要
缺點:
    一、系統複雜度增長,考慮消息的重複問題,消息丟失問題。
    二、通常消息中間件的服務崩潰了,涉及的相關係統就不可用了。
 
Rabbit 執行原理:
   消息生產方推送消息到隊列,消息放消費隊列中的消息。(下圖是基本消費模型)
   
消息模型:*******重要******
   基本消息模型         消息發送方   -----》隊列  ------》 一個消息消費方
   work 消息模型      消息發送方   -----》 隊列 ------》 多個消息消費方  
消息發送流程:
     1) 一個隊列綁定多個消費者
     2)消費者呈合做者分別處理一部分消息解決消息堆積問題。
 
 發佈訂閱消息模型(該模型包含基本與work 消息模型的  消息發佈方 -->交換機 -->隊列 -->消息訂閱方 
 1、Fanout:在廣播模式下,消息發送流程是這樣的:
  • 1) 消息生產方生產消息發送到交換機html

  • 2) 消費方監聽queue(隊列)java

  • 3) 隊列與Exchange(交換機)綁定node

  • 4) 生產者發送的消息發送到交換機(在代碼中將隊列與交換機綁定就發送給對應隊列,生產者沒法決定)。面試

  • 5) 交換機把消息發送給綁定過的全部隊列redis

  • 6) 隊列中的消息被消費者監聽到從而執行。實現一條消息被多個消費者消費spring

 2、Direct:控制發佈的消息的隊列被哪些訂閱方收到
 特色: 消息生產方會指定routingKey 的關鍵字,這樣交換機就會將消息發送給與該routingkey徹底匹配的隊列。
 例如:在路由模式中,咱們將添加一個功能 - 咱們將只能訂閱一部分消息。 例如,咱們只能將重要的錯誤消息引導到日誌文件(以節省磁盤空間),同時仍然可以在控制檯上打印全部日誌消息。可是,在某些場景下,咱們但願不一樣的消息被不一樣的隊列消費。這時就要用到Direct類型的Exchange。
   

  P:生產者,向Exchange發送消息,發送消息時,會指定一個routing key 如:rabbit 服務器

  X:Exchange(交換機),接收生產者的消息,而後把消息遞交給 與routing key徹底匹配的隊列網絡

  C1:消費者,其所在隊列指定了須要routing key 爲 error 的消息異步

  C2:消費者,其所在隊列指定了須要routing key 爲 info、error、warning 的消息分佈式

3、Topic模型 : 和Direct 同樣。只是可使用通配符進行匹配(更加靈活通用)

上圖中:Q1匹配全部的橙色動物。Q2匹配關於兔子以及懶惰動物的消息。

如下的routingKey 配置後哪些會進入Q1,Q2隊列。

  quick.orange.rabbit  Q1 Q2

  lazy.orange.elephant  Q1 Q2

  quick.orange.fox  Q1

  lazy.pink.rabbit  Q2

  quick.brown.fox  不匹配任意隊列,被丟棄

面試熱點: 如下P方 = 消息生產方   C方 = 消息消費方
 1、如何保證消息不丟失?  問到過!
  一、採用消費者消息確認機制(ACK),ACK分爲手動和自動,
  自動ACK:消費方接受到消息則隊列中的消息就會被刪除 
  手動ACK:若是在接受到消息後發生了錯誤拋異常 這種狀況應該使用手動確認 相似手動啓動關閉事務這樣
  二、採用生產者消息回執確認機制:
  消息生產者 交換機發送消息發送成功後,交換機回執ACK給消息生產者

2、若是MQ服務器掛掉怎麼辦? 
  一、搭建集羣
  二、將消息持久化,在spring集成中消息和隊列以及交換機 都是持久化的

3、如何解決隊列中的消息積壓過大?
   work 消息模型 配置多臺消息的消費方進行消費。

4、冪等性(如何解決消息被重複執行):  問到過!
消息被重複發送,例以下訂單我點了兩次也許是網絡緣由點了2次。
發生緣由:當交換機回執ACK給P方時,因爲網絡故障致使生產方未收到消息,當網絡恢復
P方沒有收到ACK回執則從新發送一條消息致使消息重複。
解決方案:
    給消息設置惟一ID,判斷該消息被消費過,而後再業務方進行去重。
實現方式兩種:
一、在ZK中建立node 當判斷是否重複的時候就去建立node 若是存在建立會報錯。
二、使用redis 當放入MQ後就往redis 中存入一個惟一id 判斷重複的時候就去看看是否存在,存在即重複。

5、延遲隊列實現方式:問到過!
場景介紹:商品訂單超過半小時自動刪除。
解決方案:(經過TTL死信 與 DLX 死信隊列實現。)
    一、設置消息的有效期,例如30Min,當超過該效期,則該信息變爲死信 (TTL)
    二、當出現死信,MQ提供對於死信處理的死信隊列,例如當訂單超過半小時,則將消息放入死信隊列,而後由綁定死信隊列的消費方進行處理,從而將訂單刪除。(DLX) 這樣就利用了MQ的特性實現了延遲隊列。
 
擴展:通常死信處理狀況有三種:
一、消息超時
二、消息被拒絕
三、隊列達到最大長度
相關文章
相關標籤/搜索