掌握Rabbitmq幾個重要概念,從一條訊息說起

李明成發表於2020-09-17

RabbitMQ 是功能強大的開源訊息代理。根據官網稱:也是使用量最廣泛的訊息佇列。就像他的口號“Messaging that just works”,開箱即用使用簡單,支援多種訊息傳輸協議(AMQP、STOMP、MQTT)。

一個應用程式或者服務如何使用RabbitMq呢?

首先會有生產者和消費者兩個角色;生產者連線到rabbit代理服務,建立一條AMQP通道,然後把生成的訊息,通過通道釋出到交換器上,交換器根據路由規則(路由key)進行繫結到或者路由到佇列上面。最後訊息到達佇列上中。消費者跟生產者一樣需要先和rabbit代理伺服器建立連線,同時建立一個訊息管道,並訂閱到佇列上,進而從佇列中獲取訊息,進行處理。這裡面涉及到訊息、交換器、繫結、佇列幾個重要的概念,下面會一一講解。整個過程如圖所示

 

訊息

生產者建立訊息,這裡的訊息是指?訊息包含兩個部分內容:有效載荷(payload)、標籤(label)。有效載荷就是你想要傳輸的資料。而標籤是描述了有效載荷,並且RabbitMQ用它來決定誰將獲得訊息的拷貝。其實通過上圖你也會發現,不同於tcp協議,因為AMQP沒有明確的接收方,只會用標籤表述這條訊息,然後把訊息交給Rabbit。rabbit會根據標籤把訊息傳送給感興趣的接收方。

佇列

訊息最終到達佇列中並等待消費。消費者通過AMQP的Basic.Consume命令訂閱。這樣做會將通道設定為接受模式,直到取消對佇列的訂閱為止。訂閱之後,消費者在消費(或者拒絕)最近的接收的那條訊息之後,就能從佇列中自動的接收下一條訊息。

注意:什麼時候訊息才會從佇列中刪除呢?這裡涉及到一個訊息確認的動作。消費者接收到的每一條訊息都必須進行確認。才會從佇列中刪除。消費者可以通過AMQP的Basic.Ack命令顯式地向rabbtmq傳送一個確認,或者在訂閱到佇列的時候就將autoAck屬性設定為true;如:autoAck: true,一旦消費者接收訊息,rabbitmq會自動視其確認了訊息。

如果消費者接收到消費1,然後在確認之前從rabbit斷開連線,rabbitmq會認為這條訊息沒有分發,然後重新分發下一個訂閱的消費者。這樣做的好處,即使你的應用程式奔潰了,也可以確保訊息會被髮送給另一個消費者進行處理,或者等待你的程式恢復正常連線,繼續消費。假設消費者A程式與rabbit斷開了連線,訊息進而會被消費者B進行消費處理。如下圖

只要消費者不進行確認,rabbit將不會給該消費者傳送訊息,因為在上一條訊息被確認之前,rabbit會認為這個消費者並沒有準備好接收下一條訊息的能力。

在沒有辦法正常確認訊息,不能一直堵塞呀,比如消費者有bug。那就使用AMPQ的Basic.Reject命令;明確的拒絕這條訊息,其中一個引數requeue如果設定了ture的話,Rabbit會把訊息重新發給下一個訂閱的消費者。

如果你檢測到一條訊息本身有錯誤而任何一個消費者都無法處理的時候,就可以把requeue設定為false,rabbitmq會把訊息從隊裡中移除,而不會把他傳送給新的消費者。

注意:這裡你可以使用對拒絕的訊息進行特殊處理,比如傳送到死信佇列或者專門收集的erro隊裡中。

小結:佇列是amqp訊息通訊的基礎模組

1.為訊息提供的處所,訊息在此等待消費
2.對負載均衡來說,佇列是絕佳方案。只需附加一堆消費者,並讓rabbitmq以迴圈的方式均勻地分配發來的訊息。
3.佇列是rabbit中訊息的最後的終點。

 

交換器、繫結

我們知道消費者如何獲取訊息,那麼現在的問題是,訊息是如何到達佇列的呢?訊息傳送到交換器,會根據確定的規則,RabbitMQ將會決定訊息該投遞到哪個佇列。這些規則稱為路由鍵(routing key)。佇列通過路由鍵繫結到交換器。當你傳送訊息到代理伺服器時,訊息將擁有一個路由鍵。如:AMPQ的Basic.Publish方法,有個引數routingKey通過他指定。即便是空的,RabbitMQ也會將其和繫結使用的路由鍵進行匹配。

交換器有四種型別:direct、fanout、topic和headers;每種型別實現了不同的路由演算法,前三個比較常用。

1.direct

這種模式非常簡單:路由鍵匹配的話,訊息就被投遞到對應的佇列。路由演算法-使用路由鍵和佇列名稱同名進行路由訊息。使用場景-直接把訊息傳送到指定佇列時使用。


預設的direct交換器,不需要進行宣告, 佇列宣告會自動繫結到預設的交換器上,並以佇列名稱作為路右鍵。使用以下程式碼傳送訊息申明的佇列中。

channel.BasicPublish(exchange: "",
                               routingKey: "hello",
                               basicProperties: null,
                               body: body);

2.fanout交換器

這種模式下,可以忽略routing key,唯一需要做的就是為新的消費者寫一段程式碼,然後宣告新的佇列並將其繫結到fanout交換器上。當你傳送一條訊息到fanout交換器上,他會把訊息投遞給所有附加在此交換器的隊裡上。路由演算法-訊息會路由到繫結到交換器上的所有佇列。使用場景-釋出訂閱的廣播功能

 

2.topic交換器

這類交換器允許不同源頭的訊息到達同一個佇列。路由演算法-根據全部或部分路由鍵匹配將訊息路由繫結的佇列上。使用場景-根據某些條件廣播到特定的佇列上。

小結:

本文主要總結了 AMQP幾個主要元素:交換器,繫結,佇列。以及一個訊息建立到消費者讀取消費的過程。 

相關文章