消息中間件 一 之 AMQP譯文(下)

3 Functional Specification 功能性說明

3.1 Server Functional Specification 服務端功能性說明

3.1.1 Messages and Content 信息和內容

在中間件處理路由和隊列系統中, 信息具有原子性. 信息中有一個內容, 內容包含一個內容頭, 用來存儲一系列屬性; 還有一個內容體, 用來保存二進制數據塊
信息可以對應多種不同的應用實體:
1 應用級別的信息
2 傳輸的文件
3 數據流中的一幀
信息可以是持久的. 持久的信息會被安全的保存在硬盤是哪個, 而且保證在出現網絡問題中也可以發送信息.
信息有一個優先級. 在相同的隊列中的信息, 高優先級會比低優先級的信息優先發送. 當爲了保證服務質量必須要刪除信息的時候, 會優先刪除低優先級的信息. 服務端不能修改接收到的和發送給消費者的消息內容體. 服務端可能會在內容頭中增加信息, 但是一定不會刪除或者修改已經存在的內容.

3.1.2 Virtual Hosts 虛擬主機

虛擬主機是服務端用來數據區分的概念, 在一個共享的結構中, 虛擬主機也方便管理.
一個虛擬主機有自己的命名空間, 一系列exchange, 消息隊列, 和所有相關的對象. 一個連接只能關聯到一個虛擬主機.
客戶端會在鑑權之後, 連接打開方法中選擇虛擬主機. 這也說明服務端的權限系統是在所有虛擬主機間共享的. 然而, 權限系統有可能對於每個虛擬主機是唯一的. 這對於共享基礎設施是非常有用的. 管理者可以使用不同的權限控制每個虛擬主機使用不同的服務器.
一個連接中的所有通道都使用一個虛擬主機, 在同一個連接中和不同的虛擬主機通信是不可能的, 在沒有關掉連接重啓的前提下也不可能修改連接的虛擬主機.
協議中沒有提供創建或者配置虛擬主機的機制, 這些服務端以一種未定義的形式完成的, 並且完全是依賴實現的.

3.1.3 Exchanges

exchange是一個包含虛擬主機的信息路由代理. 一個exchange實例(通常我們叫做一個exchange)接收信息然後路由信息(大部分是根據routing key)要麼給消息隊列要麼是內部的服務. exchange是在虛擬主機的基礎上命名的.
應用可以在權限範圍內創建, 共享, 使用, 銷燬exchange.
exchange可以是持久的, 臨時的, 或者自動銷燬. 持久exchange會一直存在直到被刪除. 臨時exchange會在服務端關閉的時候刪除. 自動刪除exchange會在不被需要的時候刪除.
服務端提供一些特殊的exchange類型. 每一種exchange類型都實現了一種特定的匹配規則和算法, 後面會介紹.
AMQP規定了一些exchange類型, 並推薦了一些. 而且, 每個服務端實現都可以增加自己的exchange類型.
一個exchange可以同時路由一條信息給多個消息隊列. 這就會創建多個信息實例, 這些消息實例會被獨立的消費掉.

3.1.3.1 The Direct Exchange Type 直連exchange

直連exchange類型工作方式如下:
1 一個消息隊列通過routing key K 綁定一個exchange
2 發送者發送信息和routing key R給這個exchange
3 如果K = R那麼信息會發送給上面的消息隊列.
服務端必須實現直連exchange類型, 而且必須在每一個虛擬主機中提前聲明至少兩個直連exchange: 一個叫做 amq.direct, 另一個沒有名字, 作爲默認exchange在發佈方法中使用.
注意, 信息隊列可以使用任何值作爲routing key, 但是大部分情況, 消息隊列會使用他們的名稱作爲routing key.
特殊情況, 所有信息隊列必須使用隊列名稱作爲routing key自動綁定到匿名的exchange上.

3.1.3.2 The Fanout Exchange Type 廣播exchange

廣播exchange工作方式如下:
1 一個信息隊列綁定到exchange不使用任何參數
2 一個發佈者發送信息給這個exchange
3 信息會被無條件的發送給這個消息隊列
廣播exchange的設計和實現是非常簡單的. 這種exchange類型和預先聲明的叫作amq.fanout的exchange是必須要有的.

3.1.3.3 The Topic Exchange Type 主題exchange

主題exchange工作方式如下:
1 信息隊列通過一個路由模板P綁定到exchange上
2 發送者發送信息到該exchange並攜帶routing key R.
3 如果R匹配P規則, 則發送信息到該信息隊列
主題exchange的routing key必須包含0或多個單詞, 由"點."分割. 每一個段子可能包含字母或者數字.
路由模板規則和routing key一致, 額外多了一些通配符, "*"匹配一個單詞, “#“匹配一個或多個單詞. 因此路由模板”*.stock.#“會匹配"usd.stock"和"eur.stock.db”, 但是不會匹配"stock.nasdaq”.
一個關於主題exchange設計的建議, 我們可以保存所有routing key到一個集合, 然後當發送者使用新的routing key時更新這個集合. 這樣可以找到一個routing key對應的綁定, 而且可以快速的找到對應的消息隊列. 主題exchange是可選的, 服務端應該事先主題exchange, 如果實現的話, 服務端必須在每個虛擬機中提前聲明一個叫做"amq.topic.*"的主題exchange.

3.1.3.4 The Headers Exchange Type

header exchange工作方式如下
1 消息隊列通過一個參數表綁定到exchange, 該參數表包含與該綁定匹配的頭信息和可選的值. 綁定中不使用routing key.
2 發送者發送信息到exchange, exchange的頭信息屬性包含一個鍵值對的表.
3 如果頭信息屬性和隊列信息匹配那麼該信息會發送到這個隊列.

3.1.3.5 The System Exchange Type 系統exchange

系統exchange工作方式如下
1 發送者發送信息給系統exchange, 包含一個routing key S
2 系統exchange發送這個信息給系統服務S
系統服務名稱以"amq."開頭, 這個是提供給AMQP使用的保留關鍵字. 其他名字服務器實現可以隨便使用. 系統exchange是可選的.

3.1.3.6 Implementation-defined Exchange Types 自定義exchange

所有非標準exchange類型必須以"x-"開頭. exchange類型沒有"x-"開頭的名稱可能以後被AMQP使用.

3.1.4 Message Queues 消息隊列

消息隊列是一個命名的先入先出緩存隊列, 它會代替一些消費者應用保存信息. 在權限範圍內, 應用可以隨意創建, 共享, 使用和銷燬消息隊列.
注意, 在某些場景下, 消息隊列可能不會表現出先入先出的特性, 比如多個消費者從一個隊列讀取信息, 或者在客戶端事務中, 或者使用優先級字段, 或者使用消息選擇器, 或者對分發實現進行特殊的優化. 唯一可以保證先入先出特性是隻有一個消費者綁定隊列的時候. 像上面那些場景中的隊列可能被描述爲弱先入先出.
消息隊列可以是持久的, 臨時的或者自動刪除的. 持久隊列會一直存在直到被刪除. 臨時隊列會在服務器關閉時刪除. 自動刪除隊列會在不再被使用時刪除.
消息隊列保存信息到內存或者硬盤或者都有. 消息隊列是在每個虛擬主機基礎上命名的.
消息隊列保存和分發信息到一個或者多個消費者. 但是消息隊列中的一條信息不會發送給超過一個客戶端, 除非是發生錯誤或者拒絕後的重發.
一個消息隊列可以同時而且獨立的持有不同類型的內容. 也就是說, 如果基礎信息和文件信息被髮送到同一個隊列, 那麼這些信息會被獨立的發送給消費者應用.

3.1.5 Bindings

binding表示消息隊列和exchange的關係. binding通過特殊的路由參數來告訴exchange哪個信息應該給哪個消息隊列. 應用可以根據需要創建和銷燬binding, 以此來驅動信息進入到消息隊列. binding的生命週期取決於它綁定的消息隊列, 當一個消息隊列銷燬時, 它的binding也會被銷燬. Queue.Bind方法的依賴於exchange類型.

3.1.6 Consumers 消費者

我們使用"消費者"來表示客戶端應用和可以控制一個客戶端應用從消息隊列接收信息的實體. 當客戶端"啓動一個消費者"就會在服務端創建一消費者實體. 當客戶端"取消消費者"就會銷燬服務端的消費者實體. 消費者屬於一個單獨的消費者通道, 這就會造成消息隊列異步發送信息給客戶端.

3.1.7 Quality of Service 服務性能

服務性能主要影響信息發送速度. 服務性能依賴於發送的內容類型. 通常情況下, 服務性能會使用"提前獲取"原則在客戶端響應信息之前指定一共有多少信息或者多少字節數據需要被髮送. 整體的目標就是提前發送信息數據來減少延遲.

3.1.8 Acknowledgements 應答

應答就是從客戶端應用發給消息隊列的一個正式信號表示自己已經成功消費信息了. 有以下兩種應答模式:
1 自動, 該模式下, 服務端會在成功發送信息給應用之後馬上刪除隊列中的信息
2 顯示的, 該模式下, 客戶端必選爲接收並消費的每一條或每一批信息發送應答信息.
客戶端可以以不同的方式實現應答, 比如在接收信息之後發送, 或者在明確處理了信息之後. 這些方式並不會對AMQP有什麼影響

3.1.9 Flow Control 流控制

流控制是用來停止從某一端來的信息流的緊急過程. 它在客戶端和服務端的工作方式是一樣的, 它是由Channel.Flow方法實現的. 流控制是唯一可以停止一個過度生產的生產者的機制. 如果消費者使用消息應答(通常意味着使用事務), 它可以使用更優雅的預取窗口機制(?).

3.1.10 Naming Conventions 命名原則

以下這些原則管理了AMQP的實體命名. 服務端和客戶端必須最受以下原則:
1 用戶定義的exchange類型的前綴必須是"x-"
2 標準的exchange實例前綴必須是"amq."
3 標準的系統服務前綴必須是"amq."
4 標準的消息隊列前綴必須是"amq."
5 所有exchange, 系統服務, 消息隊列的名稱必須在應用空間內.

3.2 AMQP Command Specification(Classes&Methods) AMQP命令說明

3.2.1 Explanatory Notes 解釋說明

AMQP方法可能爲了操作原因會定義一些特殊的最小值(比如每個隊列的消費者數量). 這些值會被定義在每個類中.
規範的AMQP實現應該在實現這些字段上有足夠的理由設置比較大的值, 最小值只是爲了滿足平臺的最基本的使用.
語法符號說明:
1 ‘S:’ 表示從服務端發送到客戶端的數據或者方法
2 ‘C:’ 表示從客戶端發送到服務端的數據或者方法
3 +實例或者+(…)表達式表示’一個或者多個實例’
4 *實例或者*(…)表達式表示’0個或者多個實例’
我們將方法定義爲:
1 一個同步請求(syn request). 發送端應該等待特殊的響應方法, 但是這個等待的實現可以是異步的.
2 一個同步響應(syn reply for XYZ)
3 一個異步的請求或者響應(async)

3.2.2 Class and Method Details 類和方法細節

This section is provided by the generated document amqp-xml-spec.odt.
本章內容在"amqp-xml-spec.odt"中

4 Technical Specifications 技術說明

4.1 IANA Assigned Port Number

標準的AMQP TCP和UDP的端口都由IANA設置爲5672. UDP端口是用於未來實現多址傳送的.

4.2 AMQP Wire-Level Format AMQP線路層結構

4.2.1 Formal Protocol Grammar 標準協議語法

我們爲AMQP提供了完整的語法(這是作爲參考提供的, 你可能會發現直接進入下一節會比較有趣, 下一節會展示各種幀類型和結構的細節.)
image.png

image.png

我們使用在IETF RFC 2234定義的增強BNF語法. 總的來說:
1 規則的名稱就是規則本身
2 終端是由一個或多個數字字符指定, 這些字符的基本解釋爲"d"或"x".(Terminals are specified by one or more numeric characters with the base interpretation of those characters indicated as ‘d’ or ‘x’)
3 規則可以通過列出規則名稱的序列來定義簡單和有序的字符串.
4 一個可選數字範圍可以使用"-“來指定.
5 使用小括號包裹的多個元素會認爲是一個元素, 而且內容是嚴格有序的.
6 被”/“分割的元素表示是可選元素
7 操作符”*"表示前面一個元素的副本. 完整的格式是: *, 是可選的數字, 表示元素最少出現的次數, 表示元素最多出現的次數.
8 element等價於*element
9 中括號中是可選的元素序列

4.2.2 Protocol Header 協議頭

客戶端在打開一個新的連接的時候必須發送一個協議頭. 下面是一個8字節序列:
image.png

該協議頭包含了四個大寫字母"AMQP", 後面是一個十進制的0, 然後是:
1 協議主版本, 參考1.4.2章節
2 協議次版本, 參考1.4.2章節
3 協議修訂版本, 參考1.4.2章節
協議的兼容模型是可以兼容HTTP協議(以常量文本初始化連接)和防火牆(根據協議決定使用什麼規則)的.
客戶端和服務端通過以下方式對協議和版本達成一致:
1 客戶端打開一個到服務端新的socket連接, 並給服務端發送協議頭.
2 服務端要麼接收要麼拒絕. 如果拒絕的話需要發送一個有效的協議頭, 並關閉連接
3 如果接收的話, 就維持連接打開狀態, 並按照協議內容繼續
如圖所示:
image.png

實現參考如下:
1 服務端可能會接收非AMQP協議, 比如HTTP
2 如果服務端不認識消息中的頭五個字節, 或者不支持客戶端請求的協議版本, 服務端此時必須返回有效的協議頭, flush socket(保證客戶端可以接收到信息) 然後關閉連接. 服務端可以打印一個日誌有助於幫助debug.
3 客戶端可以通過發送它支持的協議的最高版本給服務端來探測服務端支持的協議, 如果服務端不支持, 則使用服務端返回的低版本協議重連.
4 客戶端和服務端在描述他們實現的多種AMQP協議的時候都應該使用8字節的頭信息.

4.2.3 General Frame Format 通用的幀格式

所有的幀結構都是以一個7字節開頭的, 其中包括一個字節類型域, 兩個字節的通道域, 四個字節的長度域, 如圖所示:
image.png

AMQP定義幀類型如下:
1 type = 1, 方法幀
2 type = 2, 內容頭幀
3 type = 3, 內容體幀
4 type = 4, 心跳幀
通道號爲0表示連接中所有全局幀都可以使用, 通道號爲1-65535則需要特別指定幀.
長度域中記錄的是不包括幀尾字節的負載域的長度. 雖然AMQP被認定爲一個可靠的連接協議, 但是客戶端或者服務端的實現錯誤也需要我們使用幀尾去檢測.
實現的參考如下:
1 幀尾的字節必須是十六進制%xCE.
2 如果某一端接收到了一個不屬於定義中的幀類型, 那麼該端必須認爲這是一個嚴重的問題, 並且在不發送任何響應的情況下關閉連接.
3 當某一端在讀取幀的時候, 它一定要在解析幀之前檢測幀尾的正確性. 如果幀尾是無效的, 那麼該端必須認爲這是一個嚴重的問題, 並且在不發送任何響應的情況下關閉連接. 該端應該記錄這個問題的日誌信息, 因爲這個錯誤表示服務端或者客戶端在編碼實現上有問題.
4 一端必須不能發送超過協議規定的幀的最大長度. 如果一端接收到一個超過限制長度的幀, 那麼它必須返回一個501代碼表示一個連接異常.
5 對於所有心跳幀和連接類引用的方法幀, 內容頭幀, 內容體幀的通道號必須是0. 如果一端接收到這些幀的通道號不爲0, 那麼必須返回一個503代碼表示連接異常.

4.2.4 Method Payloads 方法負載

方法幀體包括一個不變的數據域, 叫做"參數". 所有方法體都是以可識別的類和方法的標識數字開頭的:
image.png

實現參考:
1 類id和方法id是定義在AMQP類和方法說明中的常量
2 參數域是一系列AMQP屬性, 對於每一個方法都是不一樣的.
3 對AMQP標準的類, 類id的值從%x00.01-%xEF.FF是被保留的.
4 所以類id值從%xF0.00-%xEFF.FF就可以用於實現非標準的擴展類

4.2.5 AMQP Data Fields AMQP數據域

AMQP的數據字段有兩個級別: 一是用於方法參數的本地數據字段, 二是在字段表中用於應用之間傳遞的數據字段. 字段表是本地字段的超集

4.2.5.1 Integers 整數

AMQP定義瞭如下的本地整數類型:
1 無符號字節(1字節)
2 無符號短整型(2字節)
3 無符號長整型(4字節)
4 無符號超長整形(8字節)
整數和字符串長度總是無符號的, 而且在網絡中以字節順序排序. 我們不會優化這種情況: 一個低效的系統同一個高效的系統通信.
實現者不能認爲幀中編碼後的整數在內存中是字邊界對齊的(一個Word是2字節)

4.2.5.2 Bits 比特, 位

AMQP定義了bit字段類型. bit類型會使用整個字節. 當一個幀中有兩個或者多個bit, 那麼這些bit會被壓縮成一個或多個字節. 沒有規定說幀中的bit必須連續, 但是這通常是一種減小幀大小的方法.

4.2.5.3 Strings 字符串

AMQP中的字符串長度是可變的, 它是由一個整數長度再加上零或者多個字節的數據. AMQP定義了兩種原生的字符串類型:
1 短字符串, 存儲爲一個8位的無符號整數長度再加零活多個字節數據. 短字符串可以保存最多255字節的UTF-8編碼的數據, 但是可能不包含二進制零字節(?)
2 長字符串, 存儲爲一個32位的無符號整數長度再加零活多個字節數據. 長字符串可以包含任何數據

4.2.5.4 Timestamps 時間戳

時間戳保存爲一個64位的POSIX時間格式, 精確到秒. 使用64位我們可以避免未來由於31位和32位時間格式的問題.

4.2.5.5 Field Tables 字段表

字段表示一個包含組合好的鍵值對的長字符串. 鍵值對被編碼爲:“鍵”+"值"類型+"值"本身, 其中"鍵"使用短字符串, "值"的類型使用字節. 對於字段表有效的字段類型是原生的整數, bit, 字符串, 時間戳, 這些在語法中有說明. 多字節的整數在網絡中通常會被排序.
實現參考:
1 "鍵"字段必須以’KaTeX parse error: Expected 'EOF', got '#' at position 5: '或者'#̲'開頭, 後面可能會跟着'’,’#’, 數字, 下劃線, 最多128字符.
2 服務端應該校驗"鍵"字段, 並在接收到無效"鍵"字段後返回一個503(語法錯誤)異常信息.
3 十進制數字類型將來不會支持單精度, 而是支持固定的業務, 比如貨幣匯率和金額. 這些數字被編碼爲: 一個字節表示數字位數, 後面是一個無符號長整形. The ‘decimals’ octet is not signed(?).
4 重複的字段是非法的. 端點是不允許在表中保存重複字段的.

4.2.6 Content Framing 內容設計

某些特殊的方法(生產, 發送等)會持有內容. 請參考"方法說明"章節, 看看哪些方法會持有內容. 攜帶內容的方法肯定會攜帶內容.
內容中會包含一個或多個幀如下:
1 確定的內容頭幀, 提供內容的屬性.
2 可選的, 一個或者多個內容體幀
內容幀在某一個通道內是嚴格有序的. 也就是說, 內容幀可能和其他通道的幀搞亂順序, 但是同一個通道的兩個幀順序不會亂而且不會重疊, 一個內容的內容幀也不可能跟同一個通道的方法幀搞混(?有點蒙)
注意, 任何非內容幀都明確了幀內容的結尾. 但是對於發送者是可以在不關閉通道的前提下停止發送內容, 雖然在內容頭中顯示了內容的長度(因此也知道內容幀的數量)
實現參考:
1 一端接收到不完整或者結構有問題的內容時, 必須拋出連接異常而且返回505(不希望的結構). 錯誤包括丟失內容頭, 內容頭中錯誤的類id, 丟失內容體等.

4.2.6.1 The Content Header 內容頭

內容頭負載格式如下:
image.png

實現參考:
1 類id必須和方法幀中的類id一致. 當接收到無效的類id時必須響應異常並返回501(結構錯誤)
2 weight字段沒有使用, 必須爲0;
3 體長度是一個64位的值, 用來小時整個內容體的長度, 也就是說是後面所有的內容體幀大小的總和. 0表示沒有內容體.
4 內容標識是一組bit, 標識一個有序的屬性中每一個屬性是否存在. bit從高到低排序, 15表示第一個屬性.
5 屬性標識可以超過16個. 如果最後一位bit(也就是0位)設置了屬性, 那麼也表名後面還會有一個屬性. 這裏會需要很多屬性字段.
6 屬性的值是AMQP中不同類的擁有的數據字段
7 bit屬性僅有各自的標識表示, 並不會出現在屬性列表中
8 在內容幀中通道號不能爲零. 某一端接收到一個通道爲零的內容幀時, 必須標記連接異常, 並返回504(通道錯誤).

4.2.6.2 The Content Body 內容體

內容體負載是一個可見的二進制塊, 後面跟着幀的結束位:
image.png

內容體可以按需拆分爲多個幀. 最大的幀負載長度是在建立連接的時候定義好的.
實現參考:
1 一端在處理一個劃分爲多個幀的內容體時, 要麼像原來一樣, 拆分爲更小的幀傳輸, 要麼拼接爲一個獨立的塊傳輸給應用.

4.2.7 Heartbeat Frames 心跳幀

心跳幀的作用就是通知接收端, 發送端還活着. 心跳發送的時機和頻率是在連接的時候確定的.
實現參考:
1 心跳這的通道號必須是0. 某一端接收到無效的心跳幀必須拋出連接異常, 並且返回501錯誤(幀錯誤)
2 如果某一端不支持心跳操作, 那麼在當接收到心跳後必須丟棄該心跳信息, 並且不需要發出任何錯誤信息.
3 客戶端應該在接收到Connection.Tune方法後發後發送心跳, 然後在接收到Connection.Open方法後開始監控心跳. 服務端應該在接收到Connection.Tune-Ok方法後開始發送和監控心跳.
4 每一端應該在一個特定的時間規律下盡力發送心跳. 心跳可以在任何時間發送. 任何一個字節都可以代替心跳, 所以, 只有在發送非心跳信息流量超過一個心跳週期時纔會發送心跳. 如果一端檢測到在兩個或者更多的心跳週期中沒有接收到信息, 那麼該端應該在不執行Connection.Close/Close-Ok握手方法的情況下關閉連接, 並記錄錯誤日誌.
5 在連接沒有關閉前需要一直髮送心跳信息, 包括執行關閉連接方法時和之後.

4.3 Channel Multiplexing 通道多路複用

AMQP允許端點創建多個獨立的控制線程. 每一個通道就像是一個虛擬的連接, 它們共享一個socket連接:
image.png

實現參考:
1 一個AMQP端點可以支持多個通道. 通道的最大數量是在創建連接時確定的, 端點也可以調整數量爲1.
2 每一個端點應該以一種比較公平的方式平衡通道的流量. 這種平衡可以在每幀上完成或者在每個通道的流量上完成. 端點不應該允許出現一個通道非常忙以至於"餓死"一個不忙的通道.

4.4 Visibility Guarantee 可見性保證

服務端應該保證客戶端可以一直觀察到服務端的狀態. 下面這些例子展示了客戶端可以觀察到服務端狀態指的什麼:
1 客戶端1和客戶端2連接到同一個虛擬主機
2 客戶端1聲明一個隊列
3 客戶端1收到創建成功的信息
4 客戶端1通知客戶端2關於這個隊列的信息
5 客戶端2被動聲明一個一樣的隊列
可見性保證了客戶端2可以看到這個隊列

4.5 Channel Closure 通道關閉

服務端當碰到下面這幾種情況下可以考慮關閉通道:
1 某一端執行了Close/Close-Ok握手方法來掛壁通道或者該通道所在的連接
2 某一端在通道或者該通道所在的連接上拋出異常
3 某一端在沒有執行關閉方法下關閉了通道所在的連接.
當服務端關閉通道時, 該通道上任何沒有確定的信息會被標記爲"需要重複發送". 當服務端關閉連接時, 該連接上所有標記爲自動刪除的信息都會被刪除.

4.6 Content Synchronisation 內容同步

在某些場景下, 同步請求-響應方法會對同一個通道下的異步內容發送有一定影響, 場景包括:
1 Basic.Consume和Basic.Cancel方法, 它們可以開始和停止消息的流動.
2 Basic.Recover方法可以請求服務端重新發送信息給通道
3 Queue.Bind, Queue.Unbind和Queue.Purge方法可以影響信息進入消息隊列
參考實現:
1 上述的同步請求方法在同道造成的影響在響應方法之前必須是不可見的, 在響應方法之後必須是可見的.

4.7 Content Ordering Guarantees 內容順序保證

通道中方法流的順序是穩定的: 方法接收的順序和他們被髮送的順序是一致的. 這是由AMQP所使用的TCP/IP保證的. 而且, 服務端也會以一種穩定的方式處理內容. 具體來說, 流經服務器中單一路徑的內容會保持順序. 對於單一路徑中不同的優先級內容, 我們定義了一個內容處理路徑, 該路徑包括一個進消息的通道, 一個exchange, 一個隊列, 一個出消息的通道.
實現參考:
1 服務端必須保持進入單一內容處理路徑的內容順序, 除非根據規定在Basic.Deliver方法或者Basic.Get-Ok方法中設置了"重發"字段.

4.8 Error Handling 錯誤處理

4.8.1 Exceptions 異常

使用標準的異常程序模型, AMQP不會報告成功, 只會報告失敗. AMQP定義以下兩個異常級別:
1 通道異常. 該異常會關閉引起該異常的通道. 通道異常通常是由於"軟"錯誤引起的, 這些錯誤一般不會影響剩餘的應用.
2 連接異常. 這些異常會關閉socket連接, 而且這些異常通常是由於"硬"錯誤導致的, "硬"錯誤可以是程序錯誤, 配置錯誤或者其他需要人爲接入的問題.
我們會在每個類和方法中規範的記錄這些異常.

4.8.2 Reply Code Format 響應碼格式

AMQP響應碼遵守IETF RFC 2821中"響應碼規定和原理"的定義.

4.9 Limitations 限制

AMQP說明中對爲了AMQP的擴展或者同級別的協議增加了以下限制:
1 每個連接中通道的數量: 16位的通道編碼(所以數量也限制了)
2 協議中的類數量: 16位的類id(同上)
3 每個協議類中方法的數量: 16位方法id(同上).
在數據方面的限制:
1 短字符串最大長度: 255個字節
2 一個長字符串或者表字段的最大長度爲32位
3 一個幀負載的最大長度爲32位
4 一個內容的最大長度爲64位
服務端或者客戶端也可以對一些資源做出限制, 比如同時可以建立連接的數量, 每個通道消費者的數量, 隊列的數量等. 這些不會影響操作而且也沒有詳細的規定.

4.10 Security 安全性

4.10.1 Goals and Principles 目標和原則

我們爲了防止緩存溢出的情況, 我們在所有場景都使用特定長度的緩存. 所有外部提供的數據在被讀取的時候都會檢測是否超過了允許的最大值. 無效的數據會被馬上處理, 通過關閉通道或者連接.

4.10.2 Denial of Service Attacks 拒絕服務攻擊

AMQP通過返回一個錯誤碼和關閉通道或者連接來處理錯誤. 這避免了錯誤之後不確定的狀態的發生. 服務端應該考慮在連接建立階段由於非法連接嘗試進入服務端引起的異常情況. 通常對於任何異常情況的響應在連接中的定義爲: 暫停連接(可能是一個線程)一段時間, 然後關閉網絡連接. 這些異常包括語法錯誤, 數據超長, 鑑權失敗等. 服務端應該記錄所有這樣的異常而且標誌或者阻止客戶端引起更多的錯誤.

以上爲AMQP協議全篇譯文, 下一篇我們會根據協議內容實現一個簡易RabbitMQ的客戶端(當然會參考RabbitMQ客戶端源碼~)

發佈了28 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章