RabbitMQ是一個由erlang開發的AMQP(Advanced Message Queue )的開源實現。AMQP 的出現其實也是應了廣大人民羣衆的需求,雖然在同步消息通信的世界裏有不少公開標準(如 COBAR的 IIOP ,或者是 SOAP 等),可是在異步消息處理中卻不是這樣,只有大企業有一些商業實現(如微軟的 MSMQ ,IBM 的 Websphere MQ 等),所以,在 2006 年的 6 月,Cisco 、Redhat、iMatix 等聯合制定了 AMQP 的公開標準。html
RabbitMQ是由RabbitMQ Technologies Ltd開發而且提供商業支持的。該公司在2010年4月被SpringSource(VMWare的一個部門)收購。在2013年5月被併入Pivotal。其實VMWare,Pivotal和EMC本質上是一家的。不一樣的是VMWare是獨立上市子公司,而Pivotal是整合了EMC的某些資源,如今並無上市。併發
RabbitMQ的官網是 http://www.rabbitmq.com
講解基礎概念的前面,咱們先來總體構造一個結構圖,這樣會方便們更好地去理解RabbitMQ的基本原理。
經過上面這張應用相結合的結構圖既可以清晰的看清楚總體的send Message到Receive Message的一個大體的流程。固然上面有不少名詞都相比尚未介紹到,不要着急接下來咱們就開始對其進行詳細的講解。異步
Queuesocket
Queue(隊列)RabbitMQ的做用是存儲消息,隊列的特性是先進先出。上圖能夠清晰地看到Client A和Client B是生產者,生產者生產消息最終被送到RabbitMQ的內部對象Queue中去,而消費者則是從Queue隊列中取出數據。能夠簡化成表示爲:ide
生產者Send Message 「A」被傳送到Queue中,消費者發現消息隊列Queue中有訂閱的消息,就會將這條消息A讀取出來進行一些列的業務操做。這裏只是一個消費正對應一個隊列Queue,也能夠多個消費者訂閱同一個隊列Queue,固然這裏就會將Queue裏面的消息平分給其餘的消費者,可是會存在一個一個問題就是若是每一個消息的處理時間不一樣,就會致使某些消費者一直在忙碌中,而有的消費者處理完了消息後一直處於空閒狀態,由於前面已經說起到了Queue會平分這些消息給相應的消費者。這裏咱們就可使用prefetchCount來限制每次發送給消費者消息的個數。詳情見下圖所示:高併發
這裏的prefetchCount=1是指每次從Queue中發送一條消息來。等消費者處理完這條消息後Queue會再發送一條消息給消費者。性能
Exchangefetch
咱們在開篇的時候就留了一個坑,就是那個應用結構圖裏面,消費者Client A和消費者Client B是如何知道我發送的消息是給Queue1仍是給Queue2,有沒有過這個問題,那麼咱們就來解開這個面紗,看看究竟是個什麼構造。首先明確一點就是生產者產生的消息並非直接發送給消息隊列Queue的,而是要通過Exchange(交換器),由Exchange再將消息路由到一個或多個Queue,固然這裏還會對不符合路由規則的消息進行丟棄掉,這裏指的是後續要談到的Exchange Type。那麼Exchange是怎樣將消息準確的推送到對應的Queue的呢?那麼這裏的功勞最大的當屬Binding,RabbitMQ是經過Binding將Exchange和Queue連接在一塊兒,這樣Exchange就知道如何將消息準確的推送到Queue中去。簡單示意圖以下所示:ui
在綁定(Binding)Exchange和Queue的同時,通常會指定一個Binding Key,生產者將消息發送給Exchange的時候,通常會產生一個Routing Key,當Routing Key和Binding Key對應上的時候,消息就會發送到對應的Queue中去。那麼Exchange有四種類型,不一樣的類型有着不一樣的策略。也就是代表不一樣的類型將決定綁定的Queue不一樣,換言之就是說生產者發送了一個消息,Routing Key的規則是A,那麼生產者會將Routing Key=A的消息推送到Exchange中,這時候Exchange中會有本身的規則,對應的規則去篩選生產者發來的消息,若是可以對應上Exchange的內部規則就將消息推送到對應的Queue中去。那麼接下來就來詳細講解下Exchange裏面類型。code
Exchange Type
我來用表格來描述下類型以及類型之間的區別。
上圖所示,生產者(P)生產消息1將消息1推送到Exchange,因爲Exchange Type=fanout這時候會遵循fanout的規則將消息推送到全部與它綁定Queue,也就是圖上的兩個Queue最後兩個消費者消費。
當生產者(P)發送消息時Rotuing key=booking時,這時候將消息傳送給Exchange,Exchange獲取到生產者發送過來消息後,會根據自身的規則進行與匹配相應的Queue,這時發現Queue1和Queue2都符合,就會將消息傳送給這兩個隊列,若是咱們以Rotuing key=create和Rotuing key=confirm發送消息時,這時消息只會被推送到Queue2隊列中,其餘Routing Key的消息將會被丟棄。
1.routing key爲一個句點號「. 」分隔的字符串(咱們將被句點號「. 」分隔開的每一段獨立的字符串稱爲一個單詞),如「stock.usd.nyse」、「nyse.vmw」、「quick.orange.rabbit」
2.binding key與routing key同樣也是句點號「. 」分隔的字符串
3.binding key中能夠存在兩種特殊字符「」與「#」,用於作模糊匹配,其中「」用於匹配一個單詞,「#」用於匹配多個單詞(能夠是零個)
當生產者發送消息Routing Key=F.C.E的時候,這時候只知足Queue1,因此會被路由到Queue中,若是Routing Key=A.C.E這時候會被同是路由到Queue1和Queue2中,若是Routing Key=A.F.B時,這裏只會發送一條消息到Queue2中。
這裏在對其進行簡要的表格整理:
類型名稱 | 類型描述 |
---|---|
fanout | 把全部發送到該Exchange的消息路由到全部與它綁定的Queue中 |
direct | Routing Key==Binding Key |
topic | 我這裏本身總結的簡稱模糊匹配 |
headers | Exchange不依賴於routing key與binding key的匹配規則來路由消息,而是根據發送的消息內容中的headers屬性進行匹配。 |
ConnectionFactory、Connection、Channel
ConnectionFactory、Connection、Channel都是RabbitMQ對外提供的API中最基本的對象。Connection是RabbitMQ的socket連接,它封裝了socket協議相關部分邏輯。ConnectionFactory爲Connection的製造工廠。
Channel是咱們與RabbitMQ打交道的最重要的一個接口,咱們大部分的業務操做是在Channel這個接口中完成的,包括定義Queue、定義Exchange、綁定Queue與Exchange、發佈消息等。
Connection就是創建一個TCP鏈接,生產者和消費者的都是經過TCP的鏈接到RabbitMQ Server中的,這個後續會再程序中體現出來。
Channel虛擬鏈接,創建在上面TCP鏈接的基礎上,數據流動都是經過Channel來進行的。爲何不是直接創建在TCP的基礎上進行數據流動呢?若是創建在TCP的基礎上進行數據流動,創建和關閉TCP鏈接有代價。頻繁的創建關閉TCP鏈接對於系統的性能有很大的影響,並且TCP的鏈接數也有限制,這也限制了系統處理高併發的能力。可是,在TCP鏈接中創建Channel是沒有上述代價的。