天天看點

AMQP協定的路由機制

原文連結:Routing Mechanisms For AMQP Protocol

作者:Paolo Patierno,紅帽進階軟體工程師

譯者:趙屹華 審校:劉翔宇

責編:周建丁([email protected])

未經許可,請勿轉載!

在上一篇文章裡,我們安裝了Qpid Dispatch Router,并且快速地浏覽了安裝包提供的路由管理和監控工具。

本文将介紹幾個路由器的使用例子,從簡單的配置和網絡拓撲到複雜的結構,包括AMQP發送端、接收端和代理者。代理部分并不是必須的,因為AMQP協定是一種“對等”協定,它可以直接連接配接兩個用戶端,不需要代理提供的“存儲再轉發”機制。關于這方面的介紹,可以閱讀本系列的第一篇文章。

在本文中,我将使用預設配置的路由器來示範發送端和接收端是如何與它連接配接的,以及如何通過路由器來交換消息。

路由機制

首先,值得一提的一點是路由器支援兩種不同的路由機制。

消息路由

當路由器從鍊路上收到一條消息,它使用發送端發到路由器時所指定的目的位址;如果這一位址沒有被指定,則目的位址從消息的“to”屬性中擷取。基于這個資訊,路由器查找路由表進而決定消息傳遞的路徑。它可能是直接相連的接收端,也可能是網絡中的另一個路由器來作為下一塊跳闆。當然,消息也可以被送達位址相同的多個不同的接收端。這裡的關鍵點是針對每一條接受到的消息都做一次路由決策,而且路由器内部節點之間和外部用戶端往往還有很多通信。

AMQP協定的路由機制

從上圖中可以看出,鍊路是建立在發送端和路由器以及接收端和路由器之間的。在基于消息的路由機制下,路由器和發送端以及接收端的消息交換是兩條截然不同的鍊路。

這也意味着路由器(内部的接收端)與發送端、路由器(内部的發送端)與接收端有着不同的流量控制政策。當然,如果接收端獲得的分值很低(比如10),但是路由器(内部接收端)給了發送端很大的分值(預設是250),這個內插補點需要被考慮到。如果接收端由于某些原因(收到10條消息後)關閉了連接配接,而發送端發送的消息已經超過10條(根據“accepted”标志),因為路由器無法向已經關閉的接收端繼續發送消息,它會回複一個“released”标志。

另一個有趣的地方在于消息的“處置”。路由器總是在網絡中傳播遞送和處置。當接收一條“預處置”消息時,它的屬性被傳播到了目的位址。“未處置”消息也是如此:在這種情況下,路由器需要跟蹤傳入的遞送,并将未處置消息發往目的位址;當它從最終的接收端收到已處置标志時,它将以同樣的方式回複原始發送端。

消息路由的最後一點有趣之處在于其路由模式,定義了消息在網絡中的遊走路徑:

  • 最近路線:即使有許多接收端的位址相同,消息還是按照最短路徑送往目的位址。這也意味着隻有一個接收端能夠收到消息。
  • 平衡路線:當有多個接收端的位址相同時,發往該位址的消息将分布在各個接收端上。意思是說各個接收端以類似“競争消費者”的形式每次接收不同的消息。
  • 多路傳送:這有點類似“釋出/訂閱”模式,即附着在同一個位址的所有接收端都能收到同樣的消息。

當某個位址上的所有接收者都與同一個路由器相連,我們可以近似認為“最近路線”和“平衡路線”的效果是一樣的,因為所有的路徑長度都相等,接收端與路由器的距離等級都相同。事實上并不完全這樣,因為在“最近路線”模式下路由器對各個接收端使用嚴格的循環分布,而在“平衡路線”模式下它考慮了各個接收端未處置遞送的個數,選擇其中“更快”的一個(即處置消息更快)。

舉個例子,假設有一個發送端S、兩個接收端R1和R2和一個路由器網絡,R1與S連接配接在同一個路由器上,R2連在了另一個路由器(連到前一個)。我們認為R1到S的距離是1級,R2到S的距離是2級。

在下面的場景中,按照“最近路線”模式S發送的所有消息都将被傳遞到R1。

AMQP協定的路由機制

按照“平衡路線”模式,消息分布在兩個接收端上,且與路徑長度無關。

AMQP協定的路由機制

最後,在“多路傳送”模式下所有的消息被發送到所有的接收端。

AMQP協定的路由機制

鍊路路由

當路由器收到一條附加請求時,它被傳播于整個網絡,以至于找到目的地節點,建立起一條真正的鍊路。當發送端開始給路由器發送消息,在消息層面上不需要任何決策過程,直接通過建立起的鍊路送達目的位址。你可以認為它是一種虛拟連接配接或是一條連同發送端和接收端的隧道。

AMQP協定的路由機制

如你在上述圖檔中所見,鍊路直接建在兩個端點之間,所有的活動都是通過它來進行。

從流量控制的角度來看,它直接由發送端和接收端控制;發送端給予的任何分值直接到達接收端,無需路由器的中間幹擾。穿越路由器的鍊路就像一條“隧道”,兩個端點就像是直接相連的。

對于“未處置”消息的标志也是一樣的,發送端直接收到來自接收端的标志。

不同路由模式的概念在這裡沒有意義,因為在這種情況下有一條連接配接發送端和接收端的直接路徑,是以路由器對單條消息不做任何決策,隻需要沿着鍊路傳遞每一幀資料。

我們開始吧……超級簡單!

現在,我們用一個預設配置的路由器做一個簡單的例子,隻有一個發送端和一個接收端與其相連,挂載在/my_address的位址上。

我使用了simple_recv和simple_send的C++用戶端例子,它們在Quid Proton安裝檔案夾裡都能找到。

首先,我們定義接收端的位址和接收消息的條數,比如10條消息,啟動接收端。

AMQP協定的路由機制

我們使用qdstat管理工具可以發現my_address被定義為“輸出”(從路由器到接收端)的端點,還沒有發送過消息。

AMQP協定的路由機制

之後,我們開啟發送端來發送一些自動生成的消息,比如5條消息。

AMQP協定的路由機制

如你所見,所有的消息被處置且得到确認。在接收端一側的情況如何呢?

AMQP協定的路由機制

發送端發送的所有消息都已經接收,但應用并未關閉,因為它在等待另外5條消息(當然,這隻是應用本身的行為,與路由機制無關)。

使用qdstat管理工具,我們可以看到在my_address的輸出端點有5條已發送消息。我們無法檢視的是同一個位址下的“輸入”端點(從發送端到路由器),因為消息發送之後,發送端關閉了與路由器的連接配接,這個端點也随之被删除。相信我,發送端在發送消息時這個端點确确實實是存在的!

AMQP協定的路由機制

你應該發現了我們直接将發送端和接收端相連,不需要代理者在中間存儲和轉發消息。在上述場景中,當消息被處置并且給發送端确認之後,就意味着消息真正的被接收端所接收了。

總結

在本文中,我介紹了Qpid Dispatch Router提供的消息路由的不同機制。我們可以針對不同的場景選擇最佳的方式,使得我們的分布式應用能更有效地傳遞消息。我們示範了一個簡單的例子,它不需要代理者參與,而是直接将發送端和接收端與路由器相連。在下一篇文章裡,我将不再使用預設的配置檔案,探索連接配接路由器與用戶端和代理者的不同方式,增加系統的複雜性。

繼續閱讀