咱們爲何要使用RabbitMQ?

 1、前言
服務器

       這篇文章就是講RabbitMQ的好處,你可能要說RocketMQ很好呀,咱們主要看上的就是RabbitMQ支持多語言的客戶端,很符合咱們公司的現狀,不要咱們花費功夫去搞一個客戶端,因此下面請你們不要吐槽,咱們就來靜心聽聽RabbitMQ的好;網絡

 2、RabbitMQ異步

      在消息隊列的一發一收中,咱們來看下RabbitMQ怎麼讓咱們放心使用的?首先咱們來看下RabbitMQ發收的過程:性能

      發消息的過程(生產者):設計

      1.鏈接到RabbitMQ Borker,創建一個鏈接(Connection),開啓一個信道(Channel);接口

      2.聲明交換機(Exchange);隊列

      3.聲明隊列(Queue);事務

      4.經過路由鍵(Binding Key)將交換機與路由器綁定;路由

      5.發送消息(消息包含路由鍵(Routing Key)和交換機等內容)到RabbitMQ Borker;同步

      6.交換機根據接收到路由鍵去匹配到相應的隊列中,若是找到則放入到對應的隊列中,找不到則退回(這裏是根據配置信息來的);

      7.關閉;

      收消息的過程(消費者):

      1.鏈接到RabbitMQ Borker,創建一個鏈接,開啓一個信道;

      2.請求接收RabbitMQ Borker中隊列的消息;

      3.等待RabbitMQ Borker迴應返回隊列中相應的消息;

      4.消費者接收到消息,返回確認(ack);

      5.RabbitMQ移除隊列中對應的消息;

      6.關閉;

      針對上面的過程咱們首先來談下生產者RabbitMQ是如何確保一條消息被投遞到RabbitMQ Borker中的,沒有使用過消息隊列可能聽到這裏有點懵,這裏簡單說一下,當生產者發送一條消息的時候,可能由於網絡的緣由或者RabbitMQ服務器宕機了,這個時候咱們就沒法知道一條消息是否被成功的投遞到RabbitMQ中,針對這些狀況RabbitMQ給咱們提供兩種機制來處理這個問題,一種是事務機制,另一種是消息確認機制。事務機制我想你們都很明白了,RabbitMQ客戶端提供與事務機制相關的方法有三個:channel.txSelect、channel.txCommit以及channel.txRollback。channel.txSelect用於將當前信道設置成事務模式,channel.txCommit用於提交事務,channel.txRollback用於事務回滾。當事務開啓之後,發送消息給RabbitMQ,若是消息提交成功,那麼說明RabbitMQ必定收到了消息,不然咱們能夠經過異常來捕獲,而後經過txRollback回滾,固然這種方式性能很差,事務機制將消息串行化,致使發送一條消息必須等待結果。這種方式不太好,那麼咱們接下來探討一下消息確認機制,涉及到消息確認機制的相關方法有兩個channel.confirmSelect以及channel.waitForConfirms,首先使用confirmSelect將信道設置成爲消息確認模式,當使用消息確認模式的時候,該信道上每發佈一條消息都會生成惟一的ID,當消息匹配到相應的隊列之後,就會返回一個確認的ack,這個時候生產者就知道投遞消息成功了,若是RabbitMQ發生宕機或者錯誤之後,會返回nack,則表示投遞失敗,當使用waitForConfirms實際上是將異步的模式串行化,咱們還能夠經過addConfirmLister經過ConfirmListener這個回調接口來處理返回值。RabbitMQ經過這兩種機制保證消息能被正確投遞,生產環境中都是使用批量提交,固然實際生產的時候單純這樣仍是不可以保證消息被正確投遞,好比說生產者發送消息時候網絡斷了一下,就不能保證消息被投遞過,因此下一篇我會使用延時隊列和消息打標的方式來保證消息會被100%投遞到RabbitMQ中,固然也不能說是100%只能說是99.好多個9;

      接下來咱們來探討下消費者消費的問題,若是消費者在接受到消息之後,好比出現宕機,那麼這條消息也就丟失掉了。RabbitMQ針對這種狀況,也提供了消息確認機制。當消費訂閱隊列設置autoAck設置爲fals的時候,RabbitMQ經過打標的方式,等收到消息確認的時候將隊列中的消息移除出去,若是設置爲true,當發送成功之後就將消息移除。當autoAck爲fals的時候,RabbitMQ內部會有兩種消息,一種是等待投遞消息,另一種是等待確認的消息,若是RabbitMQ一直沒有收到消費者確認的消息,而且消費此消息的消費者斷開,那麼RabbitMQ會從新發送該條消息,RabbitMQ從新投遞消息的依據就是消費者的該消息鏈接斷開。消費端能夠經過重試機制保證消息能被正常消費,若是重試還消費不掉,那麼還能夠利用下死信隊列,經過死信隊列中的內容分析程序中可能存在的異常;提到了死信隊列,咱們這裏也介紹一下,消息成爲死信有3種狀況:消費端消息被拒絕,並設置requeue參數爲false、消息過時以及隊列達到最大長度,綁定死信隊列的交換機就是死信交換機(DLX),當隊列中有死信的時候,RabbitMQ會自動將消息從新發布到設置DLX上,從而被路由死信隊列中;

     RabbitMQ自己是能夠將交換機、隊列以及消息都持久化的,固然是不建議將消息持久化的,成本過高。RabbitMQ支持集羣模式,是經過多副本的方式實現集羣模式,在RabbitMQ中叫作鏡像隊列,當Master宕機之後會按照下面步驟進行:

     1.與Master相關聯的客戶端會所有斷開;

     2.選舉最老的Savle節點做爲Master,若是這個時候全部Salve都沒處於同步狀態,則未同步的消息會被丟失掉;

     3.出於對消息可靠性的考慮,新的Master會從新入隊全部客戶端未確認的消息;

     4.若是客戶端連着slave,而且Basic.Consume消費時指定了x-cancel-on-ha-failover參數,那麼客戶端會接收到一個Consumer Cancellation Notification通知。若是未指定x-cancal-on-ha-failover參數,那麼消費者就沒法感知master宕機,會一直等待下去。

     另外RabbitMQ還支持優先級隊列、多協議、多租戶等等,性能方面的話能知足咱們公司業務,記得好像咱們這邊高峯期達到4W-5W/s,最主要的RabbitMQ社區很活躍;

3、結束

     下一篇我會使用Java和C#分別去實現上面生產者和消費者的模式,本文主要參考廝大的書和工做中使用RabbitMQ的經驗, 另外在推薦下廝大的書《RabbitMQ實戰指南》和《深刻理解Kafka:核心設計與實踐原理》,講的真的好,歡迎你們加羣438836709,歡迎你們關注我!

      

相關文章
相關標籤/搜索