RabbitMq基礎教程之基本概念
RabbitMQ是一個訊息佇列,和Kafka以及阿里的ActiveMQ從屬性來講,乾的都是一回事。訊息佇列的主要目的實現訊息的生產者和消費者之間的解耦,支援多應用之間的非同步協調工作
由於工作原因,接觸和使用rabbitmq作為生產環境下的訊息佇列,因此準備寫一些博文,記錄下這個過程中的收貨;而開篇除了環境搭建之外,就是對於其內部的基本概念進行熟悉和了解了。
基礎環境搭建可以參考: 《RabbitMq基礎教程之安裝與測試》
本文則主要集中在以下幾點:
- 幾個基本概念(Message, Publisher, Exchange, Binding, Queue, Channel, Consuer, Virtual host)
- 訊息分發的幾種策略
- ACK是什麼鬼
I. 基本概念
1. 訊息佇列
首先來一張訊息佇列的經典圖,可以劃分為三個角色: Producer, Queue, Consumer
- Queue:為承載訊息的容器,為什麼是佇列而不是棧呢?主要是因為絕大部分的場景,我們都是希望訊息是先進先出,有順序的
- Producer:生產者,就是產生訊息,並不斷往佇列塞的角色
- Consumer:消費者,也就是不斷從佇列中獲取訊息的角色
看到這個模型,如果對JDK的容器有一定的瞭解,很容易可以想到藉助 ArrayBlockingQueue
或者 ListBlockingQueue
就可以實現簡易的訊息佇列(也就是我們常說的生產者-消費者模型)
2. 例項理解訊息佇列
其實在生活中,這種模型用得非常多,就比如我們都會接觸的網購快遞,可以說是一個典型的訊息佇列的case了:
商家不斷的把商品扔給快遞公司(注意不是直接將商品給買家),而快遞公司則將商品根據地質分發對應的買家
對上面這個過程進行拆解,可以對映扮演的角色
- 商品:Message,傳遞的訊息,由商家投遞給快遞公司時,需要進行打包(一般Producer生產訊息也會將實體資料進行封裝)
- 商家:Produer 生產者
- 快遞公司: Queue,訊息的載體
- 買家:Consumer 消費者
那麼快遞公司時怎麼知道要把商品給對應的買家呢?根據包裹上的地址+電話
- 同樣訊息佇列也需要一個對映規則,實現Message和Consumer之間的路由
3. RabbitMQ基本概念
通過上面的例項對比,發現基本的訊息佇列定義的元素太少,這裡則正好可以看一下RabbitMQ是怎麼具體來實現訊息佇列的
- Message:訊息,包含訊息頭(即附屬的配置資訊)和訊息體(即訊息的實體內容)
- Publisher:生產者,向交換機發布訊息的主體
- Exchange:交換機,用來接收生產者傳送的訊息並將這些訊息路由給伺服器中的佇列
- Binding:繫結,用於給Exchange和Queue建立關係,就是我們熟知的配對的紅娘
- Queue:訊息佇列,用來儲存訊息直到傳送給消費者。它是訊息的容器,也是訊息的終點。一個訊息可投入一個或多個佇列。訊息一直在佇列裡面,等待消費者連線到這個佇列將其取走。
- Connection:連線
- Channel:通道,MQ與外部打交道都是通過Channel來的,釋出訊息、訂閱佇列還是接收訊息,這些動作都是通過Channel完成;簡單來說就是訊息通過Channel塞進佇列或者流出佇列
- Consumer:消費者,從訊息佇列中獲取訊息的主體
- Virtual Host: 虛擬主機,表示一批交換器、訊息佇列和相關物件。虛擬主機是共享相同的身份認證和加密環境的獨立伺服器域。每個 vhost 本質上就是一個 mini 版的 RabbitMQ 伺服器,擁有自己的佇列、交換器、繫結和許可權機制。vhost 是 AMQP 概念的基礎,必須在連線時指定,RabbitMQ 預設的 vhost 是 /
- Broker:訊息佇列伺服器實體
上面是一些專業的概念,那麼可以怎麼對映到前面的快遞上呢?
II. Exchange型別
生產者,將訊息投遞給Exchange,然後由Exchange將訊息路由到對應的Queue上,供消費者消費,那麼這個路由有哪些方式呢?
1. Direct策略
訊息中的路由鍵(routing key)如果和 Binding 中的 binding key 一致, 交換器就將訊息發到對應的佇列中
簡單來講,就是路由鍵與佇列名完全匹配
- 如果一個佇列繫結到交換機要求路由鍵為“dog”
- 只轉發 routing key 標記為“dog”的訊息,
- 不會轉發“dog.puppy”,也不會轉發“dog.guard”等等
- 它是完全匹配、單播的模式
舉例說明
Exchange和兩個佇列繫結在一起:
- Q1的bindingkey是orange
- Q2的binding key是black和green.
- 當Producer publish key是orange時, exchange會把它放到Q1上, 如果是black或green就會到Q2上, 其餘的Message被丟棄
2. Fanout策略
從上圖也可以看出,這種策略,將忽略所謂的routing key,將訊息分發到所有繫結的Queue上,更加類似我們理解的廣播模式
3. Topic策略
topic 交換器通過模式匹配分配訊息的路由鍵屬性,將路由鍵和某個模式進行匹配,此時佇列需要繫結到一個模式上
可以理解為直接策略的進階版,直接策略是完全精確匹配,而topic則支援正則匹配,滿足某類指定規則的(如以xxx開頭的路由鍵),可以鍵訊息分發過去
-
#
匹配0個或多個單詞 -
*
匹配不多不少一個單詞
一個更直觀的例項如下
Producer傳送訊息時需要設定routing_key,
- Q1 的binding key 是”.orange.“
- Q2 是 “..rabbit” 和 “lazy.#”:
- 產生一個
test.orange.mm
訊息,則會路由到Q1;而如果是test.orange
則無法路由到Q1,因為Q1的規則是三個單詞,中間一個為orange,不滿足這個規則的都無效 - 產生一個
test.qq.rabbit
或者lazy.qq
都可以分發到Q2;即路由key為三個單詞,最後一個為rabbit或者不限制單詞個數,主要第一個是lazy的訊息,都可以分發過來 - 如果產生的是一個
test.orange.rabbit
訊息,則Q1和Q2都可以滿足
4. Headers策略
這個實際上用得不多,它是根據Message的一些頭部資訊來分發過濾Message,忽略routing key的屬性,如果Header資訊和message訊息的頭資訊相匹配
5. 小結
主要使用的訊息分發策略有三個,直接,路由和扇形,簡單的小結下應用場景和區別
a. Direct Exchange
直接完全匹配模式,適用於精準的訊息分發
b. Topic Exchange
Routing Key的匹配模式,支援Routing Key的模糊匹配方式,更適用於多類訊息的聚合
c. Fanout Exchange
忽略Routing Key, 將訊息分配給所有的Queue,廣播模式,適用於訊息的複用場景
III. ACK
訊息佇列的一個重要指標,當有消費者獲取了訊息之後,對這個訊息我應該怎麼辦?是直接刪除還是等某個合適的機會再刪除?又或者是乾脆不刪除,就留著了?
在實際的應用場景中,訊息正常消費之後,我們希望的是這個訊息就不要了,但是消費的過程中如果出現了bug,則希望不要刪除訊息,等我修復這個bug後,可以把這個訊息重新的投遞給我
1. ack機制
Consumer接收到了訊息之後,必須返回一個ack的標誌,表示訊息是否成功消費,如果返回true,則表示消費成功了,然後這個訊息就會從RabbitMQ的佇列中刪掉;如果返回false,且設定為重新入隊,則這個訊息可以被重新投遞進來
通常實際編碼中,預設是自動ACK的,如果訊息的重要性程度較高,我們應該設定為主動ACK,在接收到訊息之後,自主的返回對應的ACK資訊
這一塊更多地內容可以檢視實際使用篇
IV. 其他
1. 參考
- Consumer Acknowledgements and Publisher Confirms
- RabbitMQ Tutorials
- RabbitMQ】三種Exchange模式——訂閱、路由、萬用字元模式
2. 一灰灰Blog: https://liuyueyi.github.io/hexblog
一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
3. 宣告
盡信書則不如,已上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
4. 掃描關注
相關文章
- RabbitMQ 3.9( 基礎 )MQ
- RabbitMQ(1)---基本概念MQ
- RabbitMQ基礎入門MQ
- RabbitMQ基礎知識MQ
- spring boot-整合RabbitMq(RabbitMq基礎)Spring BootMQ
- 基礎課程之遊戲學遊戲
- Docker基礎與基本概念Docker
- rabbitmq(一)-基礎入門MQ
- React Hooks教程之基礎篇ReactHook
- Django基礎教程之介紹Django
- Django基礎教程之工程搭建Django
- Servlet基礎教程之呼叫流程Servlet
- Java教程之RabbitMQ介紹JavaMQ
- RabbitMQ 入門之基礎概念MQ
- java基礎(六):RabbitMQ 入門JavaMQ
- RabbitMQ 佇列使用基礎教程MQ佇列
- GStreamer基礎教程02 - 基本概念
- Kernel pwn 基礎教程之 Heap Overflow
- Django基礎教程之初體驗Django
- Servlet基礎教程之生命週期Servlet
- 最基礎的Nginx教學Nginx
- Linux 的shell基礎教學Linux
- Java 多執行緒基礎(一)基本概念Java執行緒
- Django基礎教程之配置檔案詳解Django
- Django基礎教程之請求與相應Django
- Nmap掃描教程之Nmap基礎知識
- Linux基礎教程之命令的使用(轉)Linux
- 快速掌握RabbitMQ(一)——RabbitMQ的基本概念、安裝和C#驅動MQC#
- Linux的shell基礎教學(轉)Linux
- (Python基礎教程之七)Python字串操作Python字串
- golang 中 time 包使用教程之基礎使用篇Golang
- Nmap掃描教程之基礎掃描詳解
- 訊息型中介軟體之RabbitMQ基礎使用MQ
- Python基礎教程08 - 物件導向的基本概念Python物件
- Python培訓基礎教程都教哪些Python
- 很少被教的軟體開發基礎
- 菜鳥請教rbac的基礎知識
- w3schools網站的HTML教程之HTML基礎網站HTML