RabbitMQ基礎知識

BattleHeart發表於2019-05-11

RabbitMQ基礎知識

一、背景

RabbitMQ是一個由erlang開發的AMQPAdvanced Message Queue )的開源實現。AMQP 的出現其實也是應了廣大人民群眾的需求,雖然在同步訊息通訊的世界裡有很多公開標準(如 COBAR IIOP ,或者是 SOAP 等),但是在非同步訊息處理中卻不是這樣,只有大企業有一些商業實現(如微軟的 MSMQ IBM Websphere MQ 等),因此,在 2006 年的 6 月,Cisco RedhatiMatix 等聯合制定了 AMQP 的公開標準。

    RabbitMQ是由RabbitMQ Technologies Ltd開發並且提供商業支援的。該公司在20104月被SpringSourceVMWare的一個部門)收購。在20135月被併入Pivotal。其實VMWarePivotalEMC本質上是一家的。不同的是VMWare是獨立上市子公司,而Pivotal是整合了EMC的某些資源,現在並沒有上市。

RabbitMQ的官網是http://www.rabbitmq.com

二、基礎概念

講解基礎概念的前面,我們先來整體構造一個結構圖,這樣會方便們更好地去理解RabbitMQ的基本原理。

圖一

通過上面這張應用相結合的結構圖既能夠清晰的看清楚整體的send MessageReceive Message的一個大致的流程。當然上面有很多名詞都相比還沒有介紹到,不要著急接下來我們就開始對其進行詳細的講解。

Queue

Queue(佇列)RabbitMQ的作用是儲存訊息,佇列的特性是先進先出。上圖可以清晰地看到Client AClient B是生產者,生產者生產訊息最終被送到RabbitMQ的內部物件Queue中去,而消費者則是從Queue佇列中取出資料。可以簡化成表示為:

圖二

生產者Send Message “A”被傳送到Queue中,消費者發現訊息佇列Queue中有訂閱的訊息,就會將這條訊息A讀取出來進行一些列的業務操作。這裡只是一個消費正對應一個佇列Queue,也可以多個消費者訂閱同一個佇列Queue,當然這裡就會將Queue裡面的訊息平分給其他的消費者,但是會存在一個一個問題就是如果每個訊息的處理時間不同,就會導致某些消費者一直在忙碌中,而有的消費者處理完了訊息後一直處於空閒狀態,因為前面已經提及到了Queue會平分這些訊息給相應的消費者。這裡我們就可以使用prefetchCount來限制每次傳送給消費者訊息的個數。詳情見下圖所示:

圖三

這裡的prefetchCount=1是指每次從Queue中傳送一條訊息來。等消費者處理完這條訊息後Queue會再傳送一條訊息給消費者。

Exchange

我們在開篇的時候就留了一個坑,就是那個應用結構圖裡面,消費者Client A和消費者Client B是如何知道我傳送的訊息是給Queue1還是給Queue2,有沒有過這個問題,那麼我們就來解開這個面紗,看看到底是個什麼構造。首先明確一點就是生產者產生的訊息並不是直接傳送給訊息佇列Queue的,而是要經過Exchange(交換器),由Exchange再將訊息路由到一個或多個Queue,當然這裡還會對不符合路由規則的訊息進行丟棄掉,這裡指的是後續要談到的Exchange Type。那麼Exchange是怎樣將訊息準確的推送到對應的Queue的呢?那麼這裡的功勞最大的當屬BindingRabbitMQ是通過BindingExchangeQueue連結在一起,這樣Exchange就知道如何將訊息準確的推送到Queue中去。簡單示意圖如下所示:

圖4

在繫結(BindingExchangeQueue的同時,一般會指定一個Binding Key,生產者將訊息傳送給Exchange的時候,一般會產生一個Routing Key,當Routing KeyBinding Key對應上的時候,訊息就會傳送到對應的Queue中去。那麼Exchange有四種型別,不同的型別有著不同的策略。也就是表明不同的型別將決定繫結的Queue不同,換言之就是說生產者傳送了一個訊息,Routing Key的規則是A,那麼生產者會將Routing Key=A的訊息推送到Exchange中,這時候Exchange中會有自己的規則,對應的規則去篩選生產者發來的訊息,如果能夠對應上Exchange的內部規則就將訊息推送到對應的Queue中去。那麼接下來就來詳細講解下Exchange裡面型別。

Exchange Type

1.    fanout

fanout型別的Exchange路由規則非常簡單,它會把所有傳送到該Exchange的訊息路由到所有與它繫結的Queue中。

圖5

上圖所示,生產者(P)生產訊息1將訊息1推送到Exchange,由於Exchange Type=fanout這時候會遵循fanout的規則將訊息推送到所有與它繫結Queue,也就是圖上的兩個Queue最後兩個消費者消費。

2.    direct

direct型別的Exchange路由規則也很簡單,它會把訊息路由到那些binding keyrouting key完全匹配的Queue

圖6

當生產者(P)傳送訊息時Rotuing key=booking時,這時候將訊息傳送給ExchangeExchange獲取到生產者傳送過來訊息後,會根據自身的規則進行與匹配相應的Queue,這時發現Queue1Queue2都符合,就會將訊息傳送給這兩個佇列,如果我們以Rotuing key=createRotuing key=confirm傳送訊息時,這時訊息只會被推送到Queue2佇列中,其他Routing Key的訊息將會被丟棄。

3.    topic

前面提到的direct規則是嚴格意義上的匹配,換言之Routing Key必須與Binding Key相匹配的時候才將訊息傳送給Queue,那麼topic這個規則就是模糊匹配,可以通過萬用字元滿足一部分規則就可以傳送。它的約定是:

1.      routing key為一個句點號“. ”分隔的字串(我們將被句點號“. ”分隔開的每一段獨立的字串稱為一個單詞),如“stock.usd.nyse”“nyse.vmw”“quick.orange.rabbit”

2.      binding key與routing key一樣也是句點號“. ”分隔的字串

3.      binding key中可以存在兩種特殊字元“*”“#”,用於做模糊匹配,其中“*”用於匹配一個單詞,“#”用於匹配多個單詞(可以是零個)

圖7

當生產者傳送訊息Routing Key=F.C.E的時候,這時候只滿足Queue1,所以會被路由到Queue中,如果Routing Key=A.C.E這時候會被同是路由到Queue1Queue2中,如果Routing Key=A.F.B時,這裡只會傳送一條訊息到Queue2中。

4.     headers

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

這裡在對其進行簡要的表格整理:

補充說明:

ConnectionFactory、ConnectionChannel都是RabbitMQ對外提供的API中最基本的物件。ConnectionRabbitMQsocket連結,它封裝了socket協議相關部分邏輯。ConnectionFactoryConnection的製造工廠。
Channel是我們與RabbitMQ打交道的最重要的一個介面,我們大部分的業務操作是在Channel這個介面中完成的,包括定義Queue、定義Exchange、繫結QueueExchange、釋出訊息等。

Connection就是建立一個TCP連線,生產者和消費者的都是通過TCP的連線到RabbitMQ Server中的,這個後續會再程式中體現出來。

Channel虛擬連線,建立在上面TCP連線的基礎上,資料流動都是通過Channel來進行的。為什麼不是直接建立在TCP的基礎上進行資料流動呢?如果建立在TCP的基礎上進行資料流動,建立和關閉TCP連線有代價。頻繁的建立關閉TCP連線對於系統的效能有很大的影響,而且TCP的連線數也有限制,這也限制了系統處理高併發的能力。但是,在TCP連線中建立Channel是沒有上述代價的。

三、結束語

整理就到這裡了。參考內容:

http://blog.csdn.net/whycold/article/details/41119807

http://blog.csdn.net/anzhsoft/article/details/19563091

相信學過這篇文章的人都會對RabbitMQ有一個初步的瞭解。本篇文章是建立在上面兩篇文章的基礎上加上自己的理解而形成的,收穫很多。



內容均為作者獨立觀點,不代表八零IT人立場,如涉及侵權,請及時告知。