我為什么要選擇RabbitMQ ,RabbitMQ簡介,各種MQ選型對比

soゝso 2018-11-13 18:56:20 170492

前言:

    MQ 是什么?隊列是什么,MQ 我們可以理解為消息隊列,隊列我們可以理解為管道。以管道的方式做消息傳遞。

場景:

    1.其實我們在雙11的時候,當我們凌晨大量的秒殺和搶購商品,然后去結算的時候,就會發現,界面會提醒我們,讓我們稍等,以及一些友好的圖片文字提醒。而不是像前幾年的時代,動不動就頁面卡死,報錯等來呈現給用戶。

    在這業務場景中,我們就可以采用隊列的機制來處理,因為同時結算就只能達到這么多。

    2.在我們平時的超市中購物也是一樣,當我們在結算的時候,并不會一窩蜂一樣涌入收銀臺,而是排隊結算。這也是隊列機制。

對,就是排隊。一個接著一個的處理,不能插隊。

RabbitMQ簡介

AMQP,即Advanced Message Queuing Protocol,高級消息隊列協議,是應用層協議的一個開放標準,為面向消息的中間件設計。消息中間件主要用于組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。 AMQP的主要特征是面向消息、隊列、路由(包括點對點和發布/訂閱)、可靠性、安全。 RabbitMQ是一個開源的AMQP實現,服務器端用Erlang語言編寫,支持多種客戶端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現不俗。 下面將重點介紹RabbitMQ中的一些基礎概念,了解了這些概念,是使用好RabbitMQ的基礎。

ConnectionFactory、Connection、Channel

ConnectionFactory、Connection、Channel都是RabbitMQ對外提供的API中最基本的對象。Connection是RabbitMQ的socket鏈接,它封裝了socket協議相關部分邏輯。ConnectionFactory為Connection的制造工廠。 Channel是我們與RabbitMQ打交道的最重要的一個接口,我們大部分的業務操作是在Channel這個接口中完成的,包括定義Queue、定義Exchange、綁定Queue與Exchange、發布消息等。

Queue

Queue(隊列)是RabbitMQ的內部對象,用于存儲消息,用下圖表示。


RabbitMQ中的消息都只能存儲在Queue中,生產者(下圖中的P)生產消息并最終投遞到Queue中,消費者(下圖中的C)可以從Queue中獲取消息并消費。


多個消費者可以訂閱同一個Queue,這時Queue中的消息會被平均分攤給多個消費者進行處理,而不是每個消費者都收到所有的消息并處理。 


Message acknowledgment

在實際應用中,可能會發生消費者收到Queue中的消息,但沒有處理完成就宕機(或出現其他意外)的情況,這種情況下就可能會導致消息丟失。為了避免這種情況發生,我們可以要求消費者在消費完消息后發送一個回執給RabbitMQ,RabbitMQ收到消息回執(Message acknowledgment)后才將該消息從Queue中移除;如果RabbitMQ沒有收到回執并檢測到消費者的RabbitMQ連接斷開,則RabbitMQ會將該消息發送給其他消費者(如果存在多個消費者)進行處理。這里不存在timeout概念,一個消費者處理消息時間再長也不會導致該消息被發送給其他消費者,除非它的RabbitMQ連接斷開。 這里會產生另外一個問題,如果我們的開發人員在處理完業務邏輯后,忘記發送回執給RabbitMQ,這將會導致嚴重的bug——Queue中堆積的消息會越來越多;消費者重啟后會重復消費這些消息并重復執行業務邏輯…

另外pub message是沒有ack的。

Message durability

如果我們希望即使在RabbitMQ服務重啟的情況下,也不會丟失消息,我們可以將Queue與Message都設置為可持久化的(durable),這樣可以保證絕大部分情況下我們的RabbitMQ消息不會丟失。但依然解決不了小概率丟失事件的發生(比如RabbitMQ服務器已經接收到生產者的消息,但還沒來得及持久化該消息時RabbitMQ服務器就斷電了),如果我們需要對這種小概率事件也要管理起來,那么我們要用到事務。由于這里僅為RabbitMQ的簡單介紹,所以這里將不講解RabbitMQ相關的事務。

Prefetch count

前面我們講到如果有多個消費者同時訂閱同一個Queue中的消息,Queue中的消息會被平攤給多個消費者。這時如果每個消息的處理時間不同,就有可能會導致某些消費者一直在忙,而另外一些消費者很快就處理完手頭工作并一直空閑的情況。我們可以通過設置prefetchCount來限制Queue每次發送給每個消費者的消息數,比如我們設置prefetchCount=1,則Queue每次給每個消費者發送一條消息;消費者處理完這條消息后Queue會再給該消費者發送一條消息。


Exchange

在上一節我們看到生產者將消息投遞到Queue中,實際上這在RabbitMQ中這種事情永遠都不會發生。實際的情況是,生產者將消息發送到Exchange(交換器,下圖中的X),由Exchange將消息路由到一個或多個Queue中(或者丟棄)。


Exchange是按照什么邏輯將消息路由到Queue的?這個將在Binding一節介紹。 RabbitMQ中的Exchange有四種類型,不同的類型有著不同的路由策略,這將在Exchange Types一節介紹。

routing key

生產者在將消息發送給Exchange的時候,一般會指定一個routing key,來指定這個消息的路由規則,而這個routing key需要與Exchange Type及binding key聯合使用才能最終生效。 在Exchange Type與binding key固定的情況下(在正常使用時一般這些內容都是固定配置好的),我們的生產者就可以在發送消息給Exchange時,通過指定routing key來決定消息流向哪里。 RabbitMQ為routing key設定的長度限制為255 bytes。

Binding

RabbitMQ中通過Binding將Exchange與Queue關聯起來,這樣RabbitMQ就知道如何正確地將消息路由到指定的Queue了。


Binding key

在綁定(Binding)Exchange與Queue的同時,一般會指定一個binding key;消費者將消息發送給Exchange時,一般會指定一個routing key;當binding key與routing key相匹配時,消息將會被路由到對應的Queue中。這個將在Exchange Types章節會列舉實際的例子加以說明。 在綁定多個Queue到同一個Exchange的時候,這些Binding允許使用相同的binding key。 binding key 并不是在所有情況下都生效,它依賴于Exchange Type,比如fanout類型的Exchange就會無視binding key,而是將消息路由到所有綁定到該Exchange的Queue。

Exchange Types

RabbitMQ常用的Exchange Type有fanout、direct、topic、headers這四種(AMQP規范里還提到兩種Exchange Type,分別為system與自定義,這里不予以描述),下面分別進行介紹。

fanout

fanout類型的Exchange路由規則非常簡單,它會把所有發送到該Exchange的消息路由到所有與它綁定的Queue中。


上圖中,生產者(P)發送到Exchange(X)的所有消息都會路由到圖中的兩個Queue,并最終被兩個消費者(C1與C2)消費。

direct

direct類型的Exchange路由規則也很簡單,它會把消息路由到那些binding key與routing key完全匹配的Queue中。


以上圖的配置為例,我們以routingKey=”error”發送消息到Exchange,則消息會路由到Queue1(amqp.gen-S9b…,這是由RabbitMQ自動生成的Queue名稱)和Queue2(amqp.gen-Agl…);如果我們以routingKey=”info”或routingKey=”warning”來發送消息,則消息只會路由到Queue2。如果我們以其他routingKey發送消息,則消息不會路由到這兩個Queue中。

topic

前面講到direct類型的Exchange路由規則是完全匹配binding key與routing key,但這種嚴格的匹配方式在很多情況下不能滿足實際業務需求。topic類型的Exchange在匹配規則上進行了擴展,它與direct類型的Exchage相似,也是將消息路由到binding key與routing key相匹配的Queue中,但這里的匹配規則有些不同,它約定:

  • routing key為一個句點號“. ”分隔的字符串(我們將被句點號“. ”分隔開的每一段獨立的字符串稱為一個單詞),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
  • binding key與routing key一樣也是句點號“. ”分隔的字符串
  • binding key中可以存在兩種特殊字符“*”與“#”,用于做模糊匹配,其中“*”用于匹配一個單詞,“#”用于匹配多個單詞(可以是零個)


以上圖中的配置為例,routingKey=”quick.orange.rabbit”的消息會同時路由到Q1與Q2,routingKey=”lazy.orange.fox”的消息會路由到Q1與Q2,routingKey=”lazy.brown.fox”的消息會路由到Q2,routingKey=”lazy.pink.rabbit”的消息會路由到Q2(只會投遞給Q2一次,雖然這個routingKey與Q2的兩個bindingKey都匹配);routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息將會被丟棄,因為它們沒有匹配任何bindingKey。

headers

headers類型的Exchange不依賴于routing key與binding key的匹配規則來路由消息,而是根據發送的消息內容中的headers屬性進行匹配。 在綁定Queue與Exchange時指定一組鍵值對;當消息發送到Exchange時,RabbitMQ會取到該消息的headers(也是一個鍵值對的形式),對比其中的鍵值對是否完全匹配Queue與Exchange綁定時指定的鍵值對;如果完全匹配則消息會路由到該Queue,否則不會路由到該Queue。 該類型的Exchange沒有用到過(不過也應該很有用武之地),所以不做介紹。

RPC

MQ本身是基于異步的消息處理,前面的示例中所有的生產者(P)將消息發送到RabbitMQ后不會知道消費者(C)處理成功或者失敗(甚至連有沒有消費者來處理這條消息都不知道)。 但實際的應用場景中,我們很可能需要一些同步處理,需要同步等待服務端將我的消息處理完成后再進行下一步處理。這相當于RPC(Remote Procedure Call,遠程過程調用)。在RabbitMQ中也支持RPC。


  RabbitMQ  中實現RPC 的機制是:

  • 客戶端發送請求(消息)時,在消息的屬性(MessageProperties ,在AMQP 協議中定義了14中properties ,這些屬性會隨著消息一起發送)中設置兩個值replyTo (一個Queue 名稱,用于告訴服務器處理完成后將通知我的消息發送到這個Queue 中)和correlationId (此次請求的標識號,服務器處理完成后需要將此屬性返還,客戶端將根據這個id了解哪條請求被成功執行了或執行失敗)
  • 服務器端收到消息并處理
  • 服務器端處理完消息后,將生成一條應答消息到replyTo 指定的Queue ,同時帶上correlationId 屬性
  • 客戶端之前已訂閱replyTo 指定的Queue ,從中收到服務器的應答消息后,根據其中的correlationId 屬性分析哪條請求被執行了,根據執行結果進行后續業務處理

總結

本文介紹了RabbitMQ 中個人認為最重要的概念,充分利用RabbitMQ 提供的這些功能就可以處理我們絕大部分的異步業務了。

RabbitMQ 選型和對比

1.從社區活躍度

按照目前網絡上的資料,RabbitMQ activeM ZeroMQ 三者中,綜合來看,RabbitMQ 是首選。

2.持久化消息比較

ZeroMq 不支持,ActiveMq RabbitMq 都支持。持久化消息主要是指我們機器在不可抗力因素等情況下掛掉了,消息不會丟失的機制。

3.綜合技術實現

可靠性、靈活的路由、集群、事務、高可用的隊列、消息排序、問題追蹤、可視化管理工具、插件系統等等。

RabbitMq / Kafka 最好,ActiveMq 次之,ZeroMq 最差。當然ZeroMq 也可以做到,不過自己必須手動寫代碼實現,代碼量不小。尤其是可靠性中的:持久性、投遞確認、發布者證實和高可用性。

4.高并發

毋庸置疑,RabbitMQ 最高,原因是它的實現語言是天生具備高并發高可用的erlang 語言。

5.比較關注的比較, RabbitMQ 和 Kafka

RabbitMq Kafka 成熟,在可用性上,穩定性上,可靠性上,  RabbitMq  勝于  Kafka  (理論上)。

另外,Kafka 的定位主要在日志等方面, 因為Kafka 設計的初衷就是處理日志的,可以看做是一個日志(消息)系統一個重要組件,針對性很強,所以 如果業務方面還是建議選擇 RabbitMq

還有就是,Kafka 的性能(吞吐量、TPS )比RabbitMq 要高出來很多。

選型最后總結:

如果我們系統中已經有選擇  Kafka  ,或者   RabbitMq  ,并且完全可以滿足現在的業務,建議就不用重復去增加和造輪子。

可以在  Kafka  和   RabbitMq  中選擇一個適合自己團隊和業務的,這個才是最重要的。但是毋庸置疑現階段,綜合考慮沒有第三選擇。


版權所屬:SO JSON在線解析

原文地址:http://www.jngreu.co/blog/48.html

轉載時必須以鏈接形式注明原始出處及本聲明。

本文主題:

如果本文對你有幫助,那么請你贊助我,讓我更有激情的寫下去,幫助更多的人。

相關文章
為什么選擇RabbitMQRabbitMQ簡介各種MQ選型對比
各種Editor對比選擇wangEditor,wangEditor下載
為什么undefined、NaN和Infinity可以被賦值,而null不可以?
為什么很多第三方接口,都改成了基于http,直接傳遞json數據的方式來代替webservice?
什么是Referer?Referer的作用?空Referer是怎回事?
對Redis的理解,Redis是什么,Redis和Memcache誰快?
Shiro教程(一)Shiro 是什么?Shiro的簡單介紹。
中國人還相信什么什么都不相信了!
JSON是什么?它能帶來什么?它和XML比較?
Description的作用,Description對SEO有什么影響
最新文章
JS加密V6版本上線了,JS加密升級,原來的sojson.v5加密升級到JS加密第六個版本!!! 168
陜西普通話考試查詢官方,網站代碼源碼 556
阿里云和騰訊云哪個好? 322
2019年9月16日新浪短鏈API已經恢復使用,新浪短鏈服務官方已經宣布停用。本站已經攻克 2821
2019年 中秋節、國慶節放假通知來了,拼假攻略 205
記一次小失誤導致的大事件,Mysql SQL Error: 0, SQLState: null 排查過程 467
Springboot Maven 增加本地依賴包,Springboot Maven打包本地包 238
Java 獲取圖片屬性、獲取圖片EXIF屬性操作方法[metadata-extractor] 113
又拍云(Upyun)CDN、云存儲刷新鏈接緩存,API實例講解 157
Linux Centos 使用 Redis service 啟動,Redis service 腳本編寫 242
最熱文章
免費天氣API,全國天氣 JSON API接口,可以獲取五天的天氣預報 185504
我為什么要選擇RabbitMQ ,RabbitMQ簡介,各種MQ選型對比 170479
Elasticsearch教程(四) elasticsearch head 插件安裝和使用 143198
蘋果電腦Mac怎么恢復出廠系統?蘋果系統怎么重裝系統? 106435
Elasticsearch教程(六) elasticsearch Client創建 83197
Elasticsearch教程(一),全程直播(小白級別) 80947
Elasticsearch教程(二),IK分詞器安裝 78579
Elasticsearch教程(八) elasticsearch delete 刪除數據(Java) 77661
免費天氣API,天氣JSON API,不限次數獲取十五天的天氣預報 75418
Elasticsearch教程(五) elasticsearch Mapping的創建 72271

騷碼加入我們 / 千人QQ群:259217951

入群需要5元,如果沒有QQ錢包,可以先Alipay、微信,贊助然后加群主拉進。

二維碼生成 來自 >> 二維碼生成器

支付掃碼

所有贊助/開支都講公開明細,用于網站維護:贊助名單查看

正在加載... ...

北京pk一期免费计划