天天看點

RabbitMQ(一):Rabbitmq基本概念

RabbitMQ 即一個消息隊列,_主要是用來實作應用程式的異步和解耦,同時也能起到消息緩沖,消息分發的作用。RabbitMQ使用的是AMQP協定,它是一種二進制協定。預設啟動端口 5672。

RabbitMQ(一):Rabbitmq基本概念

左側 P 代表 生産者,也就是往 RabbitMQ 發消息的程式。

中間即是 RabbitMQ,_其中包括了 交換機 和 隊列。_

右側 C 代表 消費者,也就是往 RabbitMQ 拿消息的程式

那麼,其中比較重要的概念有 4 個,分别為:虛拟主機,交換機,隊列,和綁定。

  • 虛拟主機:一個虛拟主機持有一組交換機、隊列和綁定。為什麼需要多個虛拟主機呢?很簡單,RabbitMQ當中,使用者隻能在虛拟主機的粒度進行權限控制。是以,如果需要禁止A組通路B組的交換機/隊列/綁定,必須為A和B分别建立一個虛拟主機。每一個RabbitMQ伺服器都有一個預設的虛拟主機“/”。
  • 交換機:Exchange 用于轉發消息,但是它不會做存儲 ,如果沒有 Queue bind 到 Exchange 的話,它會直接丢棄掉 Producer 發送過來的消息。
    • 這裡有一個比較重要的概念:**路由鍵 ** 。消息到交換機的時候,交換機會轉發到對應的隊列中,那麼究竟轉發到哪個隊列,就要根據該路由鍵。
  • 綁定:也就是交換機需要和隊列相綁定,這其中如上圖所示,是多對多的關系。

什麼是交換機

rabbitmq的message model實際上消息不直接發送到queue中,中間有一個exchange是做消息分發,producer甚至不知道消息發送到那個隊列中去。是以,當exchange收到message時,必須準确知道該如何分發。是append到一定規則的queue,還是append到多個queue中,還是被丢棄?這些規則都是通過exchagne的4種type去定義的。

The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Actually, quite often the producer doesn't even know if a message will be delivered to any queue at all.

Instead, the producer can only send messages to an exchange. An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.

exchange是一個消息的agent,每一個虛拟的host中都有定義。它的職責是把message路由到不同的queue中。

最新版本的RabbitMQ有四種交換機類型,分别是Direct exchange、Fanout exchange、Topic exchange、Headers exchange。

四種exchange分别有以下一些屬性:

name:名稱

    Durability:持久化标志,如果為true,則表明此exchange是持久化的。

    Auto-delete:删除标志,當所有隊列在完成使用此exchange時,是否删除

    Arguments:參數

Direct Exchange – 處理路由鍵。需要将一個隊列綁定到交換機上,要求該消息與一個特定的路由鍵完全比對。這是一個完整的比對。如果一個隊列綁定到該交換機上要求路由鍵 “dog”,則隻有被标記為“dog”的消息才被轉發,不會轉發dog.puppy,也不會轉發dog.guard,隻會轉發dog。

RabbitMQ(一):Rabbitmq基本概念

實作方式:

RabbitMQ(一):Rabbitmq基本概念

Default Exchange

這種是特殊的Direct Exchange,是rabbitmq内部預設的一個交換機。該交換機的name是空字元串,所有queue都預設binding 到該交換機上。所有binding到該交換機上的queue,routing-key都和queue的name一樣。

Fanout Exchange – 不處理路由鍵。你隻需要簡單的将隊列綁定到交換機上。一個發送到交換機的消息都會被轉發到與該交換機綁定的所有隊列上。很像子網廣播,每台子網内的主機都獲得了一份複制的消息。Fanout交換機轉發消息是最快的。 

這種是publisher/subcribe模式。用來做廣播最好。所有該exchagne上指定的routing-key都會被ignore掉。

RabbitMQ(一):Rabbitmq基本概念
RabbitMQ(一):Rabbitmq基本概念

Topic Exchange – 将路由鍵和某模式進行比對。此時隊列需要綁定要一個模式上。符号“#”比對一個或多個詞,符号“*”比對不多不少一個詞。是以“audit.#”能夠比對到“audit.irs.corporate”,但是“audit.*” 隻會比對到“audit.irs”。

其中_表号比對一個word,#比對多個word和路徑,路徑之間通過.隔開。如滿足a._.c的routing-key有a.hello.c;滿足#.hello的routing-key有a.b.c.helo。

RabbitMQ(一):Rabbitmq基本概念
RabbitMQ(一):Rabbitmq基本概念

Headers exchange 

不處理路由鍵,而是根據發送的消息内容中的headers屬性進行比對。在綁定Queue與Exchange時指定一組鍵值對;當消息發送到RabbitMQ時會取到該消息的headers與Exchange綁定時指定的鍵值對進行比對;如果完全比對則消息會路由到該隊列,否則不會路由到該隊列。headers屬性是一個鍵值對,可以是Hashtable,鍵值對的值可以是任何類型。而fanout,direct,topic 的路由鍵都需要要字元串形式的 案例參考:https://blog.csdn.net/hry2015/article/details/79188615

RabbitMQ(一):Rabbitmq基本概念

類似amq.*的名稱的交換機

這些是RabbitMQ預設建立的交換機。這些隊列名稱被預留做RabbitMQ内部使用,不能被應用使用,否則抛出403 (ACCESS_REFUSED)錯誤

Dead Letter Exchange(死信交換機)

在預設情況,如果消息在投遞到交換機時,交換機發現此消息沒有比對的隊列,則這個消息将被悄悄丢棄。為了解決這個問題,RabbitMQ中有一種交換機叫死信交換機。當消費者不能處理接收到的消息時,将這個消息重新釋出到另外一個隊列中,等待重試或者人工幹預。這個過程中的exchange和queue就是所謂的”Dead Letter Exchange 和 Queue”

binding?

exchange和queue通過routing-key關聯,這兩者之間的關系是就是binding。如下圖所示,X表示交換機,紅色表示隊列,交換機通過一個routing-key去binding一個queue,routing-key有什麼作用呢?看Direct exchange類型交換機。

RabbitMQ(一):Rabbitmq基本概念

AMQP協定是一個進階抽象層消息通信協定,RabbitMQ是AMQP協定的實作。它主要包括以下元件:

RabbitMQ(一):Rabbitmq基本概念

1.Server(broker): 接受用戶端連接配接,實作AMQP消息隊列和路由功能的程序。

2.Virtual Host:其實是一個虛拟概念,類似于權限控制組,一個Virtual Host裡面可以有若幹個Exchange和Queue,但是權限控制的最小粒度是Virtual Host

3.Exchange:接受生産者發送的消息,并根據Binding規則将消息路由給伺服器中的隊列。ExchangeType決定了Exchange路由消息的行為,例如,在RabbitMQ中,ExchangeType有direct、Fanout和Topic三種,不同類型的Exchange路由的行為是不一樣的。

4.Message Queue:消息隊列,用于存儲還未被消費者消費的消息。

5.Message: 由Header和Body組成,Header是由生産者添加的各種屬性的集合,包括Message是否被持久化、由哪個Message Queue接受、優先級是多少等。而Body是真正需要傳輸的APP資料。

6.Binding:Binding聯系了Exchange與Message Queue。Exchange在與多個Message Queue發生Binding後會生成一張路由表,路由表中存儲着Message Queue所需消息的限制條件即Binding Key。當Exchange收到Message時會解析其Header得到Routing Key,Exchange根據Routing Key與Exchange Type将Message路由到Message Queue。Binding Key由Consumer在Binding Exchange與Message Queue時指定,而Routing Key由Producer發送Message時指定,兩者的比對方式由Exchange Type決定。

7.Connection:連接配接,對于RabbitMQ而言,其實就是一個位于用戶端和Broker之間的TCP連接配接。

8.Channel:信道,僅僅建立了用戶端到Broker之間的連接配接後,用戶端還是不能發送消息的。需要為每一個Connection建立Channel,AMQP協定規定隻有通過Channel才能執行AMQP的指令。一個Connection可以包含多個Channel。之是以需要Channel,是因為TCP連接配接的建立和釋放都是十分昂貴的,如果一個用戶端每一個線程都需要與Broker互動,如果每一個線程都建立一個TCP連接配接,暫且不考慮TCP連接配接是否浪費,就算作業系統也無法承受每秒建立如此多的TCP連接配接。RabbitMQ建議用戶端線程之間不要共用Channel,至少要保證共用Channel的線程發送消息必須是串行的,但是建議盡量共用Connection。

9.Command:AMQP的指令,用戶端通過Command完成與AMQP伺服器的互動來實作自身的邏輯。例如在RabbitMQ中,用戶端可以通過publish指令發送消息,txSelect開啟一個事務,txCommit送出一個事務。

在了解了AMQP模型以後,需要簡單介紹一下AMQP的協定棧,AMQP協定本身包括三層:

RabbitMQ(一):Rabbitmq基本概念

1.Module Layer,位于協定最高層,主要定義了一些供用戶端調用的指令,用戶端可以利用這些指令實作自己的業務邏輯,例如,用戶端可以通過queue.declare聲明一個隊列,利用consume指令擷取一個隊列中的消息。

2.Session Layer,主要負責将用戶端的指令發送給伺服器,在将伺服器端的應答傳回給用戶端,主要為用戶端與伺服器之間通信提供可靠性、同步機制和錯誤處理。

3.Transport Layer,主要傳輸二進制資料流,提供幀的處理、信道複用、錯誤檢測和資料表示。