RabbitMQ--基本原理
MQ全稱為Message Queue, 是一種分散式應用程式的的通訊方法,它是消費-生產者模型的一個典型的代表,producer往訊息佇列中不斷寫入訊息,而另一端consumer則可以讀取或者訂閱佇列中的訊息。RabbitMQ是MQ產品的典型代表,是一款基於AMQP協議可複用的企業訊息系統。業務上,可以實現服務提供者和消費者之間的資料解耦,提供高可用性的訊息傳輸機制,在實際生產中應用相當廣泛。本文意在介紹Rabbitmq的基本原理,包括rabbitmq基本框架,概念,通訊過程等。
系統架構
Rabbitmq系統最核心的元件是Exchange和Queue,下圖是系統簡單的示意圖。Exchange和Queue是在rabbitmq server(又叫做broker)端,producer和consumer在應用端。
producer&Consumer
producer指的是訊息生產者,consumer訊息的消費者。
Queue
訊息佇列,提供了FIFO的處理機制,具有快取訊息的能力。rabbitmq中,佇列訊息可以設定為持久化,臨時或者自動刪除。
- 設定為持久化的佇列,queue中的訊息會在server本地硬碟儲存一份,防止系統crash,資料丟失
- 設定為臨時佇列,queue中的資料在系統重啟之後就會丟失
- 設定為自動刪除的佇列,當不存在使用者連線到server,佇列中的資料會被自動刪除
Exchange
Exchange類似於資料通訊網路中的交換機,提供訊息路由策略。rabbitmq中,producer不是通過通道直接將訊息傳送給queue,而是先發送給Exchange。一個Exchange可以和多個Queue進行繫結,producer在傳遞訊息的時候,會傳遞一個ROUTING_KEY,Exchange會根據這個ROUTING_KEY按照特定的路由演算法,將訊息路由給指定的queue。和Queue一樣,Exchange也可設定為持久化,臨時或者自動刪除。
Exchange有4種類型:direct(預設),fanout, topic, 和headers,不同型別的Exchange轉發訊息的策略有所區別:
-
Direct
直接交換器,工作方式類似於單播,Exchange會將訊息傳送完全匹配ROUTING_KEY的Queue -
fanout
廣播是式交換器,不管訊息的ROUTING_KEY設定為什麼,Exchange都會將訊息轉發給所有繫結的Queue。 -
topic
主題交換器,工作方式類似於組播,Exchange會將訊息轉發和ROUTING_KEY匹配模式相同的所有佇列,比如,ROUTING_KEY為user.stock的Message會轉發給繫結匹配模式為 * .stock,user.stock, * . * 和#.user.stock.#的佇列。( * 表是匹配一個任意片語,#表示匹配0個或多個片語) -
headers
訊息體的header匹配(ignore)
Binding
所謂繫結就是將一個特定的 Exchange 和一個特定的 Queue 繫結起來。Exchange 和Queue的繫結可以是多對多的關係。
virtual host
在rabbitmq server上可以建立多個虛擬的message broker,又叫做virtual hosts (vhosts)。每一個vhost本質上是一個mini-rabbitmq server,分別管理各自的exchange,和bindings。vhost相當於物理的server,可以為不同app提供邊界隔離,使得應用安全的執行在不同的vhost例項上,相互之間不會干擾。producer和consumer連線rabbit server需要指定一個vhost。
通訊過程
假設P1和C1註冊了相同的Broker,Exchange和Queue。P1傳送的訊息最終會被C1消費。基本的通訊流程大概如下所示:
- P1生產訊息,傳送給伺服器端的Exchange
- Exchange收到訊息,根據ROUTINKEY,將訊息轉發給匹配的Queue1
- Queue1收到訊息,將訊息傳送給訂閱者C1
- C1收到訊息,傳送ACK給佇列確認收到訊息
- Queue1收到ACK,刪除佇列中快取的此條訊息
Consumer收到訊息時需要顯式的向rabbit broker傳送basic.ack訊息或者consumer訂閱訊息時設定auto_ack引數為true。在通訊過程中,佇列對ACK的處理有以下幾種情況:
- 如果consumer接收了訊息,傳送ack,rabbitmq會刪除佇列中這個訊息,傳送另一條訊息給consumer。
- 如果cosumer接受了訊息, 但在傳送ack之前斷開連線,rabbitmq會認為這條訊息沒有被deliver,在consumer在次連線的時候,這條訊息會被redeliver。
- 如果consumer接受了訊息,但是程式中有bug,忘記了ack,rabbitmq不會重複傳送訊息。
- rabbitmq2.0.0和之後的版本支援consumer reject某條(類)訊息,可以通過設定requeue引數中的reject為true達到目地,那麼rabbitmq將會把訊息傳送給下一個註冊的consumer。
Publisher:
是Message的生產者,Publisher這個Clients產生了一些Message。
Consumer:
Message的消費者,Publisher產生的Message,最終要到達Consumer這個Clients,進行消費。
Exchange:
指定訊息按什麼規則,路由到哪個Queue,Message訊息先要到達Exchange,在Server中承擔著從Produce接收Message的責任。
Queue:
到達Exchange的訊息,根據制定的規則(Routing key)到達對應的Queue,在Server中承擔著裝載Message,是Message的容器,等待被消費出去。
Routing key:
在Exchange和Queue之間隱藏有一條黑線,可以將這條黑線看成是Routing key,Exchange就是根據這些定義好的Routing key將Message送到對應的Queue中去,是Exchange和Queue之間的橋樑。
Broker:
之前一直不理解這個Broker,其實Broker就是接收和分發訊息的應用,也就是說RabbitMQ Server就是Message Broker。
VirtualHost:
虛擬主機,一個Broker裡可以開有多個VirtualHost,它的作用是用作不同使用者的許可權分離。
Connection:
是Publisher/Consumer和Broker之間的TCP連線。斷開連線的操作只會在Publisher/Consumer端進行,Broker不會斷開連線,除非出現網路故障或者Broker服務出現問題,Broker服務宕了。
Connection: Channel:
如果每一次訪問RabbitMQ就建立一個Connection,那在訊息量大的時候建立TCP Connection的開銷就會很大,導致的後果就是效率低下。
左邊的Client向右邊的Client傳送訊息,流程:
第一:獲取Conection
第二:獲取Channel
第三:定義Exchange,Queue
第四:使用一個RoutingKey將Queue Binding到一個Exchange上
第五:通過指定一個Exchange和一個RoutingKey來將訊息傳送到對應的Queue上,
第六:Consumer在接收時也是獲取connection,接著獲取channel,然後指定一個Queue,到Queue上取訊息,它對Exchange,RoutingKey及如何Binding都不關心,到對應的Queue上去取訊息就行了。
一個Publisher Client傳送訊息,哪些Consumer Client可以收到訊息,在於Exchange,RoutingKey,Queue的關係上。