MQ全稱為Message Queue, 是一種分布式應用程序的的通信方法,它是消費-生產(chǎn)者模型的一個典型的代表,producer往消息隊列中不斷寫入消息,而另一端consumer則可以讀取或者訂閱隊列中的消息。RabbitMQ是MQ產(chǎn)品的典型代表,是一款基于AMQP協(xié)議可復用的企業(yè)消息系統(tǒng)。業(yè)務上,可以實現(xiàn)服務提供者和消費者之間的數(shù)據(jù)解耦,提供高可用性的消息傳輸機制,在實際生產(chǎn)中應用相當廣泛。本文意在介紹Rabbitmq的基本原理,包括rabbitmq基本框架,概念,通信過程等。
系統(tǒng)架構(gòu)
Rabbitmq系統(tǒng)最核心的組件是Exchange和Queue,下圖是系統(tǒng)簡單的示意圖。Exchange和Queue是在rabbitmq server(又叫做broker)端,producer和consumer在應用端。
producer&Consumer
producer指的是消息生產(chǎn)者,consumer消息的消費者。
Queue
消息隊列,提供了FIFO的處理機制,具有緩存消息的能力。rabbitmq中,隊列消息可以設置為持久化,臨時或者自動刪除。
設置為持久化的隊列,queue中的消息會在server本地硬盤存儲一份,防止系統(tǒng)crash,數(shù)據(jù)丟失
設置為臨時隊列,queue中的數(shù)據(jù)在系統(tǒng)重啟之后就會丟失
設置為自動刪除的隊列,當不存在用戶連接到server,隊列中的數(shù)據(jù)會被自動刪除
Exchange
Exchange類似于數(shù)據(jù)通信網(wǎng)絡中的交換機,提供消息路由策略。rabbitmq中,producer不是通過信道直接將消息發(fā)送給queue,而是先發(fā)送給Exchange。一個Exchange可以和多個Queue進行綁定,producer在傳遞消息的時候,會傳遞一個ROUTING_KEY,Exchange會根據(jù)這個ROUTING_KEY按照特定的路由算法,將消息路由給指定的queue。和Queue一樣,Exchange也可設置為持久化,臨時或者自動刪除。
Exchange有4種類型:direct(默認),fanout, topic, 和headers,不同類型的Exchange轉(zhuǎn)發(fā)消息的策略有所區(qū)別:
Direct直接交換器,工作方式類似于單播,Exchange會將消息發(fā)送完全匹配ROUTING_KEY的Queue
fanout廣播是式交換器,不管消息的ROUTING_KEY設置為什么,Exchange都會將消息轉(zhuǎn)發(fā)給所有綁定的Queue。
topic主題交換器,工作方式類似于組播,Exchange會將消息轉(zhuǎn)發(fā)和ROUTING_KEY匹配模式相同的所有隊列,比如,ROUTING_KEY為user.stock的Message會轉(zhuǎn)發(fā)給綁定匹配模式為 * .stock,user.stock, * . * 和#.user.stock.#的隊列。( * 表是匹配一個任意詞組,#表示匹配0個或多個詞組)
headers消息體的header匹配(ignore)
Binding
所謂綁定就是將一個特定的 Exchange 和一個特定的 Queue 綁定起來。Exchange 和Queue的綁定可以是多對多的關系。
virtual host
在rabbitmq server上可以創(chuàng)建多個虛擬的message broker,又叫做virtual hosts (vhosts)。每一個vhost本質(zhì)上是一個mini-rabbitmq server,分別管理各自的exchange,和bindings。vhost相當于物理的server,可以為不同app提供邊界隔離,使得應用安全的運行在不同的vhost實例上,相互之間不會干擾。producer和consumer連接rabbit server需要指定一個vhost。
通信過程
假設P1和C1注冊了相同的Broker,Exchange和Queue。P1發(fā)送的消息最終會被C1消費。基本的通信流程大概如下所示:
P1生產(chǎn)消息,發(fā)送給服務器端的Exchange
Exchange收到消息,根據(jù)ROUTINKEY,將消息轉(zhuǎn)發(fā)給匹配的Queue1
Queue1收到消息,將消息發(fā)送給訂閱者C1
C1收到消息,發(fā)送ACK給隊列確認收到消息
Queue1收到ACK,刪除隊列中緩存的此條消息
Consumer收到消息時需要顯式的向rabbit broker發(fā)送basic.ack消息或者consumer訂閱消息時設置auto_ack參數(shù)為true。在通信過程中,隊列對ACK的處理有以下幾種情況:
如果consumer接收了消息,發(fā)送ack,rabbitmq會刪除隊列中這個消息,發(fā)送另一條消息給consumer。
如果cosumer接受了消息, 但在發(fā)送ack之前斷開連接,rabbitmq會認為這條消息沒有被deliver,在consumer在次連接的時候,這條消息會被redeliver。
如果consumer接受了消息,但是程序中有bug,忘記了ack,rabbitmq不會重復發(fā)送消息。
rabbitmq2.0.0和之后的版本支持consumer reject某條(類)消息,可以通過設置requeue參數(shù)中的reject為true達到目地,那么rabbitmq將會把消息發(fā)送給下一個注冊的consumer。
Conclusion
本文和大家一起學習了rabbitmq的一些基礎知識,在之后的博文中,筆者將會和大家一起分享更多的Rabbitmq知識
RabbitMQ