訊息佇列中介軟體 AMQP 學習

2021-08-25 13:59:12 字數 4810 閱讀 8700

amqp-advanced message queue protocol是什麼

訊息**(message brokers)從發布者(publishers)亦稱生產者(producers)那兒接收訊息,並根據既定的路由規則把接收到的訊息傳送給處理訊息的消費者(consumers)。

發布者(publisher)發布訊息時可以給訊息指定各種訊息屬性(message meta-data)。有些屬性有可能會被訊息**(brokers)使用,然而其他的屬性則是完全不透明的,它們只能被接收訊息的應用所使用。

從安全角度考慮,網路是不可靠的,接收訊息的應用也有可能在處理訊息的時候失敗。基於此原因,amqp模組包含了乙個訊息確認(message acknowledgements)的概念:當乙個訊息從佇列中投遞給消費者後(consumer),消費者會通知一下訊息**(broker),這個可以是自動的也可以由處理訊息的應用的開發者執行。當「訊息確認」被啟用的時候,訊息**不會完全將訊息從佇列中刪除,直到它收到來自消費者的確認回執(acknowledgement)。

在某些情況下,例如當乙個訊息無法被成功路由時,訊息或許會被返回給發布者並被丟棄。或者,如果訊息**執行了延期操作,訊息會被放入乙個所謂的死信佇列中。此時,訊息發布者可以選擇某些引數來處理這些特殊情況。

佇列,交換機和繫結統稱為amqp實體(amqp entities)。

amqp 0-9-1的**提供了四種交換機

name(交換機型別)

default pre-declared names(預宣告的預設名稱)

direct exchange(直連交換機)

(empty string) and amq.direct

fanout exchange(扇型交換機)

amq.fanout

topic exchange(主題交換機)

amq.topic

headers exchange(頭交換機)

amq.match (and amq.headers in rabbitmq)

除交換機型別外,在宣告交換機時還可以附帶許多其他的屬性,其中最重要的幾個分別是:

交換機可以有兩個狀態:持久(durable)、暫存(transient)。持久化的交換機會在訊息**(broker)重啟後依舊存在,而暫存的交換機則不會(它們需要在**再次上線後重新被宣告)。然而並不是所有的應用場景都需要持久化的交換機。

(1)預設交換機 default exchange

預設交換機(default exchange)實際上是乙個由訊息**預先宣告好的沒有名字(名字為空字串)的直連交換機(direct exchange)。它有乙個特殊的屬性使得它對於簡單應用特別有用處:那就是每個新建佇列(queue)都會自動繫結到預設交換機上,繫結的路由鍵(routing key)名稱與佇列名稱相同。

舉個栗子:當你宣告了乙個名為"search-indexing-online"的佇列,amqp**會自動將其繫結到預設交換機上,繫結(binding)的路由鍵名稱也是為"search-indexing-online"。因此,當攜帶著名為"search-indexing-online"的路由鍵的訊息被傳送到預設交換機的時候,此訊息會被預設交換機路由至名為"search-indexing-online"的佇列中。換句話說,預設交換機看起來貌似能夠直接將訊息投遞給佇列,儘管技術上並沒有做相關的操作。

(2)直連交換機 direct exchange

直連型交換機(direct exchange)是根據訊息攜帶的路由鍵(routing key)將訊息投遞給對應佇列的。直連交換機用來處理訊息的單播路由(unicast routing)(儘管它也可以處理多播路由)。下邊介紹它是如何工作的:

直連交換機經常用來迴圈分發任務給多個工作者(workers)。當這樣做的時候,我們需要明白一點,在amqp 0-9-1中,訊息的負載均衡是發生在消費者(consumer)之間的,而不是佇列(queue)之間。

直連型交換機圖例:

(3) 扇形交換機 funout exchange

扇型交換機(funout exchange)將訊息路由給繫結到它身上的所有佇列,而不理會繫結的路由鍵。如果n個佇列繫結到某個扇型交換機上,當有訊息傳送給此扇型交換機時,交換機會將訊息的拷貝分別傳送給這所有的n個佇列。扇型用來交換機處理訊息的廣播路由(broadcast routing)。

因為扇型交換機投遞訊息的拷貝到所有繫結到它的佇列,所以他的應用案例都極其相似:

體育新聞**可以用它來近乎實時地將比分更新分發給移動客戶端

分發系統使用它來廣播各種狀態和配置更新

在群聊的時候,它被用來分發訊息給參與群聊的使用者。(amqp沒有內建presence的概念,因此xmpp可能會是個更好的選擇)

扇型交換機圖例:

(4)主題交換機 topic exchange

主題交換機(topic exchanges)通過對訊息的路由鍵和佇列到交換機的繫結模式之間的匹配,將訊息路由給乙個或多個佇列。主題交換機經常用來實現各種分發/訂閱模式及其變種。主題交換機通常用來實現訊息的多播路由(multicast routing)。

使用案例:

(5)頭交換機head exchange

有時訊息的路由操作會涉及到多個屬性,此時使用訊息頭就比用路由鍵更容易表達,頭交換機(headers exchange)就是為此而生的。頭交換機使用多個訊息屬性來代替路由鍵建立路由規則。通過判斷訊息頭的值能否與指定的繫結相匹配來確立路由規則。

我們可以繫結乙個佇列到頭交換機上,並給他們之間的繫結使用多個用於匹配的頭(header)。這個案例中,訊息**得從應用開發者那兒取到更多一段資訊,換句話說,它需要考慮某條訊息(message)是需要部分匹配還是全部匹配。上邊說的「更多一段訊息」就是"x-match"引數。當"x-match"設定為「any」時,訊息頭的任意乙個值被匹配就可以滿足條件,而當"x-match"設定為「all」的時候,就需要訊息頭的所有值都匹配成功。

頭交換機可以視為直連交換機的另一種表現形式。頭交換機能夠像直連交換機一樣工作,不同之處在於頭交換機的路由規則是建立在頭屬性值之上,而不是路由鍵。路由鍵必須是乙個字串,而頭屬性值則沒有這個約束,它們甚至可以是整數或者雜湊值(字典)等。

amqp中的佇列(queue)跟其他訊息佇列或任務佇列中的佇列是很相似的:它們儲存著即將被應用消費掉的訊息。

持久化佇列(durable queues)會被儲存在磁碟上,當訊息**(broker)重啟的時候,它依舊存在。沒有被持久化的佇列稱作暫存佇列(transient queues)。並不是所有的場景和案例都需要將佇列持久化。

持久化的佇列並不會使得路由到它的訊息也具有永續性。倘若訊息**掛掉了,重新啟動,那麼在重啟的過程中持久化佇列會被重新宣告,無論怎樣,只有經過持久化的訊息才能被重新恢復。

amqp提供兩種刪除資訊的方式

當乙個消費者接收到某條訊息後,處理過程有可能成功,有可能失敗。應用可以向訊息**表明,本條訊息由於「拒絕訊息(rejecting messages)」的原因處理失敗了(或者未能在此時完成)。當拒絕某條訊息時,應用可以告訴訊息**如何處理這條訊息——銷毀它或者重新放入佇列。當此佇列只有乙個消費者時,請確認不要由於拒絕訊息並且選擇了重新放入佇列的行為而引起訊息在同乙個消費者身上無限迴圈的情況發生。

amqp模型中的訊息(message)物件是帶有屬性(attributes)的。

有些屬性是被amqp**所使用的,但是大多數是開放給接收它們的應用直譯器用的。有些屬性是可選的也被稱作訊息頭(headers)。他們跟http協議的x-headers很相似。訊息屬性需要在訊息被發布的時候定義。

amqp的訊息除屬性外,也含有乙個有效載荷 - payload(訊息實際攜帶的資料),它被amqp**當作不透明的位元組陣列來對待。訊息**不會檢查或者修改有效載荷。訊息可以只包含屬性而不攜帶有效載荷。它通常會使用類似json這種序列化的格式資料,為了節省,協議緩衝器和messagepack將結構化資料序列化,以便以訊息的有效載荷的形式發布。amqp及其同行者們通常使用"content-type" 和 "content-encoding" 這兩個欄位來與訊息溝通進行有效載荷的辨識工作,但這僅僅是基於約定而已。

訊息能夠以持久化的方式發布,amqp**會將此訊息儲存在磁碟上。如果伺服器重啟,系統會確認收到的持久化訊息未丟失。簡單地將訊息傳送給乙個持久化的交換機或者路由給乙個持久化的佇列,並不會使得此訊息具有持久化性質:它完全取決與訊息本身的持久模式(persistence mode)。將訊息以持久化方式發布時,會對效能造成一定的影響(就像資料庫操作一樣,健壯性的存在必定造成一些效能犧牲)。

amqp連線通常是長連線。amqp是乙個使用tcp提供可靠投遞的應用層協議。amqp使用認證機制並且提供tls(ssl)保護。

有些應用需要與amqp**建立多個連線。無論怎樣,同時開啟多個tcp連線都是不合適的,因為這樣做會消耗掉過多的系統資源並且使得防火牆的配置更加困難。amqp 0-9-1提供了通道(channels)來處理多連線,可以把通道理解成共享乙個tcp連線的多個輕量化連線。

在涉及多執行緒/程序的應用中,為每個執行緒/程序開啟乙個通道(channel)是很常見的,並且這些通道不能被執行緒/程序共享。

乙個特定通道上的通訊與其他通道上的通訊是完全隔離的,因此每個amqp方法都需要攜帶乙個通道號,這樣客戶端就可以指定此方法是為哪個通道準備的。

為了在乙個單獨的**上實現多個隔離的環境(使用者、使用者組、交換機、佇列 等),amqp提供了乙個虛擬主機(virtual hosts - vhosts)的概念。

參考**

amqp協議簡介(來自官網翻譯)

中介軟體 訊息佇列

參考 訊息佇列的四種應用場景 訊息佇列設計思路 1 非同步處理 使用者註冊時,可以同時將 傳送郵件 和 傳送簡訊 功能放到訊息佇列中實現。可以提高使用者響應時間,提高系統吞吐量。2 應用解耦 使用者下單和庫存扣賬中使用訊息,可以防止庫存系統出問題後,導致使用者下單失敗。3 流量削峰 秒殺活動中,由於...

中介軟體 訊息中介軟體學習總結

冪等 在程式設計中.乙個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函式,或冪等方法,是指可以使用相同引數重複執行,並能獲得相同結果的函式。這些函式 不會影響系統狀態,也不用擔心重複執行會對系統造成改變。例如,getusername 和settrue 函式就是乙個冪等函式....

中介軟體之訊息佇列

訊息佇列本質上就是乙個中轉站,如下圖,生產者將訊息傳送到乙個叫訊息佇列的容器中,然後消費者從容器中去取自己需要的訊息。有沒有覺得和分布式系統的註冊中心有點像啊。這就是最原始最簡單的訊息佇列 佇列模型,允許多個生產者往同乙個佇列中傳送訊息,但同一時刻只能有乙個消費者獲取訊息,消費完後訊息被刪除。由於佇...