RabbitMQ學習之:(十一)AMQP.0-10規範,中文翻譯1,2,3章 (轉載)

From:http://blog.sina.com.cn/s/blog_4aba0c8b0100p6ho.htmlphp

From: http://blog.sina.com.cn/s/blog_4aba0c8b0100p6hb.htmlhtml

 

 

 

AMQP.0-10中文版——概述

第1章 概述

1.1.  本文檔的目標

這份文檔定義了高級消息隊列協議,這個協議使得聽從該協議的客戶端應用和消息中間件服務器之間可以互相通訊。爲了徹底實現互操做性,咱們還定義了消息中間件服務的標準行爲。java

咱們面對這個領域有經驗的技術讀者,同時還提供了足夠的規範和指南,一個合適的技術工程師能夠根據這些文檔在任何硬件平臺上用各類編程語言來構建聽從該協議的解決方案。c++

1.2.  專利

AMQP的設計目標之一是它的概念都來自於現有的、無產權阻礙的、普遍推行的標準——好比由互聯網工程任務組和萬維網頒佈的標準。算法

所以,咱們相信僅用衆所周知的一些技術就可以實現AMQP服務,好比現有的開源網絡程序和電子郵件路由軟件或者那些技術專家們所熟悉的技術。數據庫

1.3.  摘要

1.3.1.  什麼是AMQP

高級消息隊列協議使得聽從該規範的客戶端應用和消息中間件服務器的全功能互操做成爲可能。編程

1.3.2.  爲何要用AMQP

咱們的目標是實現一種在全行業普遍使用的標準消息中間件技術,以便下降企業和系統集成的開銷,而且向大衆提供工業級的集成服務。緩存

咱們的宗旨是經過AMQP,讓消息中間件的能力最終被網絡自己所具備,而且經過消息中間件的普遍使用發展出一系列有用的應用程序。安全

1.3.3.  AMQP的範圍

爲了徹底實現消息中間件的互操做性,須要充分定義網絡協議和消息代理服務的功能語義。服務器

所以,AMQP定義網絡協議(AMQP是協議!)和代理服務以下:

  1. 一套肯定的消息交換功能,也就是「高級消息交換協議模型」。AMQP模型包括一套用於路由和存儲消息的功能模塊,以及一套在這些模塊之間交換消息的規則。
  2. 一個網絡線級協議(數據傳輸格式),客戶端應用能夠經過這個協議與消息代理和它實現的AMQP模型進行交互通訊。

能夠只實現AMQP協議規範中的的部分語義,可是咱們相信明確的描述這些語義有助於理解這個協議。

1.3.4.  高級消息交換協議

1.3.4.1.  AMQP模型

咱們須要明確的定義服務器的語義,由於全部服務器實現都應該保持這些語義的一致性,不然就沒法進行互操做。

所以AMQP模型描述了一套模塊化的組件以及這些組件之間進行鏈接的標準規則。

在服務器中,三個主要功能模塊鏈接成一個處理鏈完成預期的功能:

  1. 「exchange」接收發布應用程序發送的消息,並根據必定的規則將這些消息路由到「消息隊列」。
  2. 「message queue」存儲消息,直到這些消息被消費者安全處理完爲止。
  3. 「binding」定義了exchange和message queue之間的關聯,提供路由規則。

使用這個模型咱們能夠很容易的模擬出存儲轉發隊列和主題訂閱這些典型的消息中間件概念。

一個AMQP服務器相似於郵件服務器,exchage相似於消息傳輸代理(email裏的概念),message queue相似於郵箱。Binding定義了每個傳輸代理中的消息路由表,發佈者將消息發給特定的傳輸代理,而後傳輸代理將這些消息路由到郵箱中,消費者從這些郵箱中取出消息。

在之前的中間件系統的應用場景中,發佈者直接將消息發送給郵箱或者郵件列表。

區別就在於用戶能夠控制message queue與exchage的鏈接規則,這能夠作不少有趣的事情,好比定義一條規則:「將全部包含這樣這樣的消息頭的消息都複製一份再發送到消息隊列中」。

AMQP模型有如下目標:

  1. 支持金融服務領域的語義要求。
  2. 支持金融服務領域所要求的性能要求。
  3. 可以很方便的擴展新的消息路由和隊列。
  4. 經過AMQP協議(AMQP和AMQP Protocol的是總體和部分的關係),服務器應用能夠經過編程的方式來實現具體的功能語義。
  5. 簡單而靈活。

1.3.4.2.  AMQP協議

AMQP協議是一個二進制協議,擁有一些現代特色:多信道、協商式、異步、安全、跨平臺、中立、高效。

AMQP一般被劃分爲三層:

模型層定義了一套命令(按功能分類),客戶端應用能夠利用這些命令來實現它的業務功能。

會話層負責將命令從客戶端應用傳遞給服務器,再將服務器的應答傳遞給客戶端應用,會話層爲這個傳遞過程提供可靠性、同步機制和錯誤處理。

傳輸層提供幀處理、信道複用、錯誤檢測和數據表示。

實現者能夠將傳輸層替換成任意傳輸協議,只要不改變AMQP協議中與客戶端應用程序相關的功能。實現者還可使用其餘高層協議中的會話層。

AMQP模型的設計由如下幾個需求所驅動:

  1. 保證聽從AMQP規範的服務器實現之間可以進行互操做。
  2. 爲服務質量提供顯示控制。
  3. 支持全部消息中間件的功能:消息交換、文件傳輸、流傳輸、遠程進程調用等。
  4. 兼容已有的消息API規範(好比Sun公司的JMS規範)。
  5. 造成一致和明確的命名。
  6. 經過AMQP協議能夠完整的配置服務器線路(TODO:server wiring是啥意思?)。
  7. 使用命令符號能夠很容易的映射成應用級別的API。
  8. 明肯定義每個操做只作一件事情。

AMQP傳輸層的設計由如下幾個主要的需求所驅動,這些需求不分前後次序:

  1. 使用可以快速打包解包的二進制編碼來保證數據的緊湊性。
  2. 可以處理任意大小的消息。
  3. 容許零拷貝數據傳輸(好比遠程DMA)。
  4. 一個鏈接支持多個會話。
  5. 保證會話可以從網絡錯誤、服務器失效中恢復。
  6. 爲了長期存在,沒有隱含的內置限制(TODO:To be long-lived,with no significant in-built limitations)。
  7. 異步傳輸消息。
  8. 可以很容易的處理新的和變化的需求。
  9. 高版本的AMQP規範可以兼容低版本的規範。
  10. 使用強斷言模型來保證應用程序的可修復性。
  11. 保持編程語言的中立性。
  12. 適宜使用代碼生成工具生成協議處理模塊。

1.3.5.  功能範圍

咱們支持各類消息交換的體系結構:

  1. 存儲轉發(多個消息發送者,單個消息接收者)。
  2. 分佈式事務(多個消息發送者,多個消息接收者)。
  3. 發佈訂閱(多個消息發送者,多個消息接收者)。
  4. 基於內容的路由(多個消息發送者,多個消息接收者)。
  5. 文件傳輸隊列(多個消息發送者,多個消息接收者)。
  6. 點對點鏈接(單個消息發送者,單個消息接收者)。

1.4.  本文檔的結構

本文檔分紅兩個部分:

  1. 「概念」部分將對AMQP的概念作一個簡單的介紹,描述AMQP怎麼工做,以及AMQP的用途。
  2. 「標準」部分將對AMQP的模型層、會話層的每一個組成部分作精確的定義,還將定義AMQP在網絡上傳輸的二進制消息結構。
  3. 咱們用IETF RFC2119中的術語定義:必須、沒必要、應該、不該該和能夠(詳見http://www.ietf.org/rfc/rfc2119.txt)。
  4. 當咱們討論聽從AMQP規範的服務器的具體行爲時,咱們使用術語「服務器」來表示這些服務器。
  5. 當咱們討論聽從AMQP規範的客戶端應用的具體行爲時,咱們使用術語「客戶端」來表示這些客戶端應用。
  6. 咱們使用「端點」來表示「服務器或者客戶端」。
  7. 除非另有說明,全部數字都是十進制的。
  8. 協議中的常量都用大寫字母的名字來表示。AMQP的實現若是須要在代碼或者文檔中定義和使用這些常量,必須用這些名字來表示。
  9. 屬性名、命令或者控制參數,以及幀字段都用小寫字母的名字來表示。AMQP的實現必須在代碼或者文檔中與之保持一致。

1.5.  約定

1.5.1.  定義

1.5.2.  版本號

AMQP版本用兩個版本號表示——主版本號和次版本號。咱們約定版本由主版本號後面加小數點再加上次版本號組成(好比1-3表示主版本號爲1,次版本號爲3)。

  1. 主版本號和次版本號能夠用0到255以內的全部值。
  2. 主版本號保持不變,次版本號遞增。當AMQP工做組提高主版本號時,次版本號將被設置爲0。所以,有可能出現這樣的版本序列:1-2,1-3,1-4,2-0,2-1……
  3. 一旦本協議發佈以後(主版本號大於1),應儘可能防止次版本號遞增到9。不過在發佈以前(版本0-x),因爲會對本協議進行頻繁的修訂,能夠不遵照這條約定。
  4. 一旦本協議發佈以後(主版本號大於1),同一個主版本不一樣次版本的實現必須向後兼容。而在發佈以前,這些次版本的實現不須要兼容。
  5. 大於或者等於99的主版本號用於測試和開發目的。

1.5.3.  技術術語

  1. AMQP模型(AMQP Model):一個由關鍵實體和語義表示的邏輯框架,聽從AMQP規範的服務器必須提供這些實體和語義。爲了實現本規範中定義的語義,客戶端能夠發送命令來控制AMQP服務器。
  2. 鏈接(Connection):一個網絡鏈接,好比TCP/IP套接字鏈接。
  3. 會話(Session):端點之間的命名對話。在一個會話上下文中,保證「剛好傳遞一次」。
  4. 信道(Channel):多路複用鏈接中的一條獨立的雙向數據流通道。爲會話提供物理傳輸介質。
  5. 客戶端(Client):AMQP鏈接或者會話的發起者。AMQP是非對稱的,客戶端生產和消費消息,服務器存儲和路由這些消息。
  6. 服務器(Server):接受客戶端鏈接,實現AMQP消息隊列和路由功能的進程。也稱爲「消息代理」。
  7. 端點(Peer):AMQP對話的任意一方。一個AMQP鏈接包括兩個端點(一個是客戶端,一個是服務器)。
  8. 搭檔(Partner):當描述兩個端點之間的交互過程時,使用術語「搭檔」來表示「另外一個」端點的簡記法。好比咱們定義端點A和端點B,當它們進行通訊時,端點B是端點A的搭檔,端點A是端點B的搭檔。
  9. 片斷集(Assembly):段的有序集合,造成一個邏輯工做單元。
  10. 段(Segment):幀的有序集合,造成片斷集中一個完整子單元。
  11. 幀(Frame):AMQP傳輸的一個原子單元。一個幀是一個段中的任意分片。
  12. 控制(Control):單向指令,AMQP規範假設這些指令的傳輸是不可靠的。
  13. 命令(Command):須要確認的指令,AMQP規範規定這些指令的傳輸是可靠的。
  14. 異常(Exception):在執行一個或者多個命令時可能發生的錯誤狀態。
  15. 類(Class):一批用來描述某種特定功能的AMQP命令或者控制。
  16. 消息頭(Header):描述消息數據屬性的一種特殊段。
  17. 消息體(Body):包含應用程序數據的一種特殊段。消息體段對於服務器來講徹底不透明——服務器不能查看或者修改消息體。
  18. 消息內容(Content):包含在消息體段中的的消息數據。
  19. 交換器(Exchange):服務器中的實體,用來接收生產者發送的消息並將這些消息路由給服務器中的隊列。
  20. 交換器類型(Exchange Type):基於不一樣路由語義的交換器類。
  21. 消息隊列(Message Queue):一個命名實體,用來保存消息直到發送給消費者。
  22. 綁定器(Binding):消息隊列和交換器之間的關聯。
  23. 綁定器關鍵字(Binding Key):綁定的名稱。一些交換器類型可能使用這個名稱做爲定義綁定器路由行爲的模式。
  24. 路由關鍵字(Routing Key):一個消息頭,交換器能夠用這個消息頭決定如何路由某條消息。
  25. 持久存儲(Durable):一種服務器資源,當服務器重啓時,保存的消息數據不會丟失。
  26. 臨時存儲(Transient):一種服務器資源,當服務器重啓時,保存的消息數據會丟失。
  27. 持久化(Persistent):服務器將消息保存在可靠磁盤存儲中,當服務器重啓時,消息不會丟失。
  28. 非持久化(Non-Persistent):服務器將消息保存在內存中,當服務器重啓時,消息可能丟失。
  29. 消費者(Consumer):一個從消息隊列中請求消息的客戶端應用程序。
  30. 生產者(Producer):一個向交換器發佈消息的客戶端應用程序。
  31. 虛擬主機(Virtual Host):一批交換器、消息隊列和相關對象。虛擬主機是共享相同的身份認證和加密環境的獨立服務器域。客戶端應用程序在登陸到服務器以後,能夠選擇一個虛擬主機。

下面這些術語在AMQP規範的上下文中沒有特別的意義:

  1. 主題:一般指發佈消息;AMQP規範用一種或多種交換器來實現主題。
  2. 服務:一般等同於服務器。AMQP規範使用「服務器」這個術語來兼容IETF的標準術語,而且明確了協議中每一個部分的角色(兩方也多是AMQP服務)。
  3. 消息代理:等同於服務器。AMQP規範使用術語「客戶端」和「服務器」來兼容IETF的標準術語

 

 

 

第2章 AMQP模型

2.1.  AMQP模型簡介

本節說明爲了保證AMQP實現之間的互操做性而必須標準化的功能語義。

下面的圖展現了AMQP模型的功能組件:

咱們能夠將中間件服務器概要的定義爲:它是一個數據服務器,它接受消息而且對這些消息作兩個主要的處理;它按照任意規則將這些消息路由給消費者,當消費者來不及接受這些消息時,它會將消息存儲在內存或者硬盤中。

之前的一些消息中間件服務器把路由和存儲這兩個任務都交給一個總體式的處理引擎去處理,AMQP模型將一些較小的模塊化的插件來組合成更加多元化和健壯的處理引擎。AMQP將這些任務劃分紅兩個不一樣的角色:

在交換器和消息隊列之間有一個明確的接口組件,名爲「綁定器」,稍後咱們會提到這個組件。AMQP的價值來自於如下三個主要特性:

可以建立任意類型的交換器和消息隊列(一些類型在標準中已經定義,用戶還能夠添加一些自定義的類型做爲服務器的擴展)。 可以結合交換器和消息隊列建立出知足任何需求的消息處理系統。 可以經過協議徹底控制AMQP模型中的組件。

事實上,AMQP提供了動態編程的功能語義。

2.1.1.  消息隊列

消息隊列將消息存儲在內存或者硬盤中,並按順序把這些消息傳遞給一個或者多個消費者應用程序。消息隊列是消息存儲和分發的實體。每個消息隊列都徹底獨立。

消息隊列有多個屬性:私有隊列或共享隊列,持久存儲隊列或臨時存儲隊列,永久隊列或臨時隊列。經過選擇指望的屬性,咱們能夠用消息隊列來實現傳統的中間件實體,好比:

標準的存儲轉發隊列,存儲消息,並根據輪詢調度的算法向多個訂閱者分發消息。 臨時回覆隊列,存儲消息,並將消息轉發給單個訂閱者。回覆隊列一般是臨時的,它對單個訂閱者而言是私有的。 訂閱隊列,存儲來自於不一樣消息源的消息,並將消息轉發給單個訂閱者。訂閱隊列一般是臨時的,它對單個訂閱者而言是私有的。(別跟主題弄混淆了)

這幾種隊列類型並無在AMQP規範中定義,它們只是展現消息隊列如何使用的例子。建立其餘類型的隊列實體也很簡單,好比持久、共享訂閱的隊列。

2.1.2.  交換器

交換器接受從生產者應用程序發送的消息,並根據事先定義的規則將這些消息路由給消息隊列。這些規則叫「綁定器」。交換器是匹配和路由消息的實體,也就是說,它檢查消息並使用綁定器中的路由表,決定如何將消息轉發給消息隊列。交換器不存儲消息。

術語「交換器」本質上便是一類算法,也是這樣一個算法的實例。更準確的說,咱們稱之爲「交換類型」和「交換實例」。

AMQP規範定義了一些標準交換器類型,它們涵蓋了消息傳輸過程當中基本的消息路由類型。AMQP服務器將提供這些交換器的默認實例,使用AMQP的應用程序還能夠添加一些自定義的交換器實例。交換器類型都有各自的名稱,服務器能夠根據這些名稱建立出對應的交換器。交換器實例一樣也有名稱,應用程序能夠在代碼中使用這個名稱來指明應用程序如何與隊列綁定和發佈消息。

交換器的概念是爲了定義一個模型,AMQP服務器能夠利用這個模型來擴展消息路由行爲。

2.1.3.  綁定關鍵字

通常狀況下,交換器會檢查某條消息的消息屬性、消息頭字段、消息體內容,以及從源端接收到的相似數據,而後決定如何路由這條消息。

在大多數簡單的狀況下,交換器只檢查一個關鍵字段,咱們稱之爲「綁定關鍵字」。綁定關鍵字是一個虛擬地址,交換器用這個地址來決定如何路由消息。

對於點對點路由,綁定關鍵字是消息隊列的名稱。

對於主題發佈訂閱路由,綁定關鍵字是主題階層值(TODO:topic hierarchy value,對規範還不熟悉,不知道這是什麼意思)。

在更復雜的狀況下,綁定關鍵字可能會基於消息頭字段和/或消息體內容。

2.1.4.  AMQP與電子郵件的比較

若是咱們和電子郵件系統作一個比較,咱們會發現AMQP中的概念早已存在:

AMQP消息相似電子郵件。 消息隊列相似於郵箱。 消費者相似於獲取和刪除電子郵件的電子郵件客戶端。 交換器相似於檢查郵件並決定如何路由給郵箱的電子郵件傳輸代理, 路由關鍵字對應於電子郵件中的「To:or Cc:or Bcc:」地址,不包含服務器信息(路由動做徹底是在AMQP服務器內部完成的)。 每個交換器實例都相似於單獨的電子郵件傳輸代理進程,處理一些電子郵件子域或者是一些特殊的電子郵件通訊(TODO:handling some email sub-domain, or particular type of email traffic)。 綁定器相似於郵件傳輸代理中路由表的一個條目。

AMQP的強大之處在於咱們能夠動態的添加隊列(郵箱)、交換器(電子郵件傳輸代理)、綁定器(路由項),還能夠經過不一樣的方式將這些組件串聯在一塊兒,這樣作遠比簡單的將目的地址映射成郵箱名稱要靈活得多。

咱們沒必要對電子郵件和AMQP作深刻比較,由於它們有本質區別。AMQP須要應付的場景是在服務器中路由和存儲消息。(TODO:if only for banal reasons such as maintaining transparent performance)服務器內部路由消息和在服務器之間路由消息須要面對大相徑庭的問題,也有着大相徑庭的解決方法。

爲了在AMQP服務器之間路由消息,用戶必須明確創建鏈接橋——爲了在這些分離的實體間傳遞消息,其中一個AMQP服務器將扮演另外一個服務器的客戶端。這種工做方式是爲了迎合使用AMQP的企業的須要,由於建立這些鏈接橋可能須要考慮業務流程、合同契約和安全問題。這個模型也讓AMQP「垃圾消息」難以在網絡上傳播。

2.1.5.  消息流程

下圖展現了消息在AMQP服務器中的處理流程:

2.1.5.1.  消息生命週期

一條AMQP消息由一組消息頭屬性加上一個非透明的消息體組成。

生產者應用程序首先經過客戶端API建立一條消息,將應用數據設置在消息體中,也許還會對某些消息屬性賦值,而後爲消息設置路由標籤——這些標籤相似於一個地址,也多是任意結構的標識,最後將消息發送給服務器中的某個交換器。

當消息到達服務器時,交換器將這些消息路由給一組一樣存在於服務器中的消息隊列。若是消息沒法路由,交換器可能會根據生產者的要求,直接丟棄或者拒絕這些消息,或者將它們路由給其餘交換器。

一條消息能夠存在於多個消息隊列,AMQP服務器實現可能會用不一樣的技術來應對這樣的場景:複製消息、引用計數等,使用不一樣的技術並不會影響互操做性,然而,當消息路由到多個消息隊列時,這條消息對於每個消息隊列而言都是相同的,沒有惟一性標識來代表這條消息產生於不一樣的複製過程。

當消息到達某個消息隊列時,消息隊列當即嘗試將它經過AMQP協議傳遞給客戶端應用程序。若是消息沒法傳遞,消息隊列會保存這條消息,而且等待消費者的訂閱。

可被送達的消息將會從內部緩衝區被刪除。刪除動做可能會當即發生,或者在訂閱者成功處理且明確接受消息以後發生。訂閱者決定在何時如何接受消息,也能夠將消息放回到隊列中,或者在沒法處理消息的時候拒絕它。

生產者發送消息和訂閱者接受消息都是事務性處理過程,當一個應用程序扮演這兩個角色時——應用程序常常這樣幹——先發送和接受消息,而後再提交或者回滾事務。

2.1.5.2.  生產者視角

經過與電子郵件系統的比較,咱們能夠看到生產者並不是直接將消息發送到消息隊列中。直接將消息發送到消息隊列會破壞AMQP模型內在的抽象性(TODO:the abstraction in the AMQP Model),就好象是容許電子郵件不通過電子郵件傳輸代理而直接被投遞到郵箱中,這會致使管理員在生產者和郵箱之間難以插入郵件過濾器、處理程序、垃圾郵件檢測程序等。

AMQP模型採用與電子郵件系統相同的原理:全部消息被髮送到交換器,交換器根據規則信息檢查消息,而後將它們路由給其餘組件,交換器的這兩個動做對於用戶來講都是透明的。

2.1.5.3.  消費者視角

當咱們以消費者的視角來審視AMQP時,咱們會發現一些它與電子郵件的不一樣之處。電子郵件客戶端都被動接受郵件——它們讀取郵箱中的電子郵件,可是它們沒法決定郵箱應該存放哪些電子郵件。AMQP客戶端也能夠像電子郵件客戶端同樣被動的接受消息,也就是說,咱們能夠寫一個應用程序,這個應用程序被動的接收某個消息隊列中的消息。

然而,咱們也容許AMQP客戶端執行如下三個操做:

就像是咱們擁有這樣的郵件系統:

咱們能夠看到AMQP更像是一種編程語言,它可以定義AMQP模型中的各個組件如何鏈接和交互。這也是咱們的目標之一——經過協議實現系統行爲的可編程化。

2.1.5.4.  默認流程

大多數集成系統不須要這麼精確的定義消息流程。就像針對業餘攝影愛好者同樣,大多數AMQP用戶須要「全自動」模式。AMQP使用兩個簡單的概念來實現這一點:

事實上,默認的綁定器使得生產者直接將消息發送到消息隊列中,它模擬了傳統消息中間件中最簡單的「發送到目的地」消息分發機制。

2.2.  虛擬主機

虛擬主機由它本身的名字空間和一組交換器、消息隊列和全部關聯的對象組成。每一個鏈接必須和某個虛擬主機關聯。

客戶端在認證以後選擇虛擬主機,這要求服務器上全部虛擬主機共享服務器的受權策略,對每個虛擬主機而言,受權策略能夠是惟一的。

同一鏈接中全部信道都和同一個虛擬主機通訊。同一個鏈接既不可能與不一樣的虛擬主機同時通訊,也不可能不重建鏈接就直接切換鏈接到另外一個虛擬主機。

協議沒有提供建立或者配置虛擬主機的機制,這些機制徹底由服務器自定義。

2.3.  交換器

交換器是虛擬主機中的路由代理。交換器實例(俗稱「一個交換器」)接受消息和路由信息(路由關鍵字),而後將消息發送給消息隊列或者是一些AMQP服務器廠商擴展的內部服務。對於每一個虛擬主機內部,交換器有獨一無二的名字。

應用程序在其權限範圍以內能夠自由的建立、共享、使用和銷燬交換器實例。

交換器能夠是持久的、臨時的或者自動刪除的。持久交換器會一直存在於服務器,直到它被顯式刪除;臨時交換器會工做到服務器被關閉時爲止;而一旦沒有應用程序使用自動刪除交換器,它就會被服務器自動刪除掉。

服務器提供了一組特定的交換器類型,每個交換器類型都實現了一種特定的匹配和路由算法,咱們將在下一節介紹這些算法。AMQP要求服務器實現至少實現一小部分交換器類型,而且建議實現更多的類型以知足應用的須要,每個服務器實現還能夠實現其餘自定義交換器類型。

交換器可以並行的將一條消息路由到多個消息隊列,這將建立多個被獨立消費的消息實例。

2.3.1.  交換器類型

每個交換器類型都實現了一種特定的路由算法。後面將會介紹一些標準交換器類型,可是有兩種類型特別重要:

請注意:

2.3.1.1.  直接式交換器類型 (Direct Exchange)

直接式交換器類型提供了這樣的消息路由機制:經過精確匹配消息的路由關鍵字,將消息路由到零個或者多個隊列中,綁定關鍵字用來將隊列和交換器綁定到一塊兒。這讓咱們能夠構建經典的點對點隊列消息傳輸模型,不過和任何已定義的交換器類型同樣,當消息的路由關鍵字與多個綁定關鍵字匹配時,消息可能會被髮送到多個隊列中。

直接式交換器的工做方式以下:

服務器必須實現直接式交換器類型,必須在每個虛擬隊列中事先聲明至少兩個直接式交換器:一個名爲「amq.direct」,一個沒有公共名稱——做爲向其餘服務器傳輸消息的默認交換器(無名交換器)。值得注意的是,消息隊列可使用任意合法的綁定關鍵字,可是一般會使用它們本身的名稱做爲綁定關鍵字。

特別強調的是,全部使用各自消息隊列名稱做爲綁定關鍵字的消息隊列必須自動和無名交換器綁定在一塊兒。

2.3.1.2.  廣播式交換器類型(Fanout Exchange)

廣播式交換器類型提供了這樣的路由機制:不論消息的路由關鍵字是什麼,這條消息都會被路由到全部與該交換器綁定的隊列中。

廣播式交換器類型的工做方式以下:

不使用任何參數將消息隊列與交換器綁定在一塊兒。 發佈者(直接式交換器類型描述中的producer變成了publisher,已經隱含了二種交換器類型的區別)向交換器發送一條消息。 消息被無條件的傳遞到全部和這個交換器綁定的消息隊列中。

服務器必須實現扇出式交換器類型,必須在每個虛擬隊列中事先聲明至少一個扇出式交換器:名爲「amq.fanout」。

2.3.1.3.  主題式交換器類型(Topic Exchange)

主題式交換器類型提供了這樣的路由機制:經過消息的路由關鍵字和綁定關鍵字的模式匹配,將消息路由到被綁定的隊列中。這種路由器類型能夠被用來支持經典的發佈/訂閱消息傳輸模型——使用主題名字空間做爲消息尋址模式,將消息傳遞給那些部分或者所有匹配主題模式的多個消費者。

主題交換器類型的工做方式以下:

綁定關鍵字用零個或多個標記構成,每個標記之間用「.」字符分隔。綁定關鍵字必須用這種形式明確說明,並支持通配符:「*」匹配一個詞組,「#」零個或多個詞組。

所以綁定關鍵字「*.stock.#」匹配路由關鍵字「usd.stock」和「eur.stock.db」,可是不匹配「stock.nasdaq」。

這種交換器類型是可選的。

服務器應該(不是必須)實現主題式交換器類型,在這種狀況下,服務器必須事先在每個虛擬主機中定義至少一個主題式交換器:名爲「amq.topic」。

2.3.1.4.  消息頭式交換器類型

消息頭式交換器類型提供了複雜的、多重部分表達式路由,它的路由機制基於AMQP消息頭屬性。

消息頭式交換器的工做方式以下:

消息隊列根據一個參數列表與交換器綁定,列表中的參數包括被匹配的消息頭字段和一些可選的字段值。 發佈者向交換器發送一條消息,這條消息的消息頭屬性包含了名值列表。 若是消息頭中的名值列表與參數列表匹配,消息將被傳遞給對應的消息隊列。

匹配算法由參數列表中的某個特殊的名值對所控制,這個參數的名稱是「x-match」,它能取一到兩個值,用來決定如何匹配其餘名值:

若是符合如下兩種條件之一,綁定參數中的一個字段與消息頭中的一個字段匹配:(1)綁定參數的某個字段沒有值,且消息頭有這個屬性字段;(2)綁定參數的某個字段有值,且消息頭中有這個屬性字段並具備相同的值。

除了‘x-match’,以「x-」開頭的字段都做爲保留字段,目前這些字段會被服務器直接忽略。

服務器應該(不是必須)實現消息頭式交換器類型,在這種狀況下,服務器必須事先在每個虛擬主機中定義至少一個消息頭式交換器:名爲「amq.match」。

2.3.1.5.  系統交換器類型

系統交換器的工做方式以下:

AMQP規範以「amq.」開頭的系統服務名稱,這些名稱做爲保留名稱,其餘全部名稱均可以由服務器實現任意使用。這個交換器類型是可選實現的。

2.3.1.6.  自定義交換類型

全部沒有在規範中定義的交換器類型的名稱必須以「x-」開頭。不以「x-」開頭的交換器類型做爲保留類型,被AMQP標準在未來使用。

2.3.2.  交換器生命週期

每個AMQP服務器都會事先建立一些交換器(更準確一點,「交換器實例」)。這些交換器會一直存在與服務器中,它們不能被銷燬

AMQP應用程序也能建立它們本身的交換器,AMQP並不使用「create」之類的命令,它使用「declare」命令,這意味着「若是不存在就建立,不然繼續」。應用程序能夠建立一個私有的交換器,而且當它們的工做完成時刪除這些交換器。AMQP提供了一個命令來刪除交換器,可是通常應用程序不會這樣作。

在本章的例子中,咱們假設全部交換器都在服務器啓動時被建立出來。咱們不會展現應用程序如何聲明交換器。

2.4.  消息隊列

消息隊列是一個具名緩衝區,它們表明一組消費者應用程序保存消息。應用程序在其權限範圍以內能夠自由的建立、共享、使用和消費消息隊列。

消息隊列提供了有限制的先進先出保證。服務器會將從某一個生產者發出的同等優先級的消息按照它們進入隊列的順序傳遞給某個消費者,萬一某些消息不能被消費者處理,它們可能會被打亂順序從新傳遞。

消息隊列能夠是持久的、臨時的或者自動刪除的。臨時消息隊列會工做到服務器被關閉時爲止;而一旦沒有應用程序使用自動刪除消息隊列,它就會被服務器自動刪除掉。只要用戶(客戶端)擁有相應的權限,任何隊列均可以被顯式刪除。

消息隊列將消息保存在內存、硬盤,或者這兩種介質的組合之中。

消息隊列限定在虛擬主機範圍之中。

隊列名必須包含1到255個字符。隊列名首字符限定爲字母a-z或者A-Z,數字0-9,或者下劃線‘_’;接下來的其餘字符必須是合法的UTF-8字符。

消息隊列保存消息,並將消息分發給一個或多個訂閱客戶端。

消息隊列會跟蹤消息的獲取狀況,消息要出隊就必須被獲取(acquire和consume是兩個動做,先執行acquire,至關於對消息加鎖)。這阻止了多個客戶端同時獲取和消費同一條消息,也能夠被用來作單個隊列多個消費者之間的負載均衡。

若是消息被客戶端釋放或者最初被髮送的消息沒有被獲取,一個隊列中的消息可能會被髮送給多個客戶端。爲了容許客戶端可以安全的瀏覽隊列中的內容,消息隊列可能會將未被獲取的消息分發給客戶端。

2.4.1.  消息隊列屬性

當客戶端應用程序建立消息隊列時,它能夠爲這個消息隊列選擇幾個重要的屬性:

名稱——當應用程序共享一個消息隊列,它們預先協商好的消息隊列名。 持久的——若是指定這個屬性,消息隊列會在服務器重啓以後仍然可以繼續工做。不過在重啓以後,消息隊列會丟失非持久消息。 自動刪除的——若是指定這個屬性,當全部客戶端再也不使用這個隊列時,服務器會當即或者不久以後把這個隊列刪除掉。 
2.4.2.  消息隊列生命週期

下面是兩種主要的消息隊列生命週期:

持久消息隊列,在多個訂閱者之間共享,獨立存在——也就是說,無論有沒有訂閱者接收消息,它們都會持續存在並收集消息。臨時消息隊列,私有的,只有某個訂閱者可使用,當訂閱者退出鏈接後,消息隊列會被刪除掉。

還有些其餘類型的消息隊列生命週期,好比共享消息隊列,當最後一個訂閱者退出鏈接後,消息隊列會被刪除掉。

下圖展現了臨時消息隊列的建立和刪除過程:

2.5.  綁定器

綁定器表示消息隊列和交換器之間的關聯關係(對於實現者和用戶而言,binding應該是一個實體,而不是抽象的relationship)。綁定器指定了路由參數,這些參數告訴交換器哪些消息能夠發送給隊列。

應用程序根據須要建立和銷燬綁定器,驅動消息流入消息隊列。綁定器的生存期由使用它的消息隊列和交換器決定,當消息隊列或者交換器被銷燬,綁定器也會被銷燬。

客戶端應用程序使用命令構造綁定器,用來綁定它正在使用的消息隊列和交換器。咱們能夠下面這段僞代碼來表示一個綁定命令:

Exchange.Bind <exchange> TO <queue> WHERE <condition>

Exchange.Bind的特殊語義取決於交換器類型。

讓咱們來看看三個典型的用例:共享隊列、私有回覆隊列和發佈訂閱隊列。

2.5.1.  構造共享隊列

共享隊列是典型中間件中的點對點隊列。在AMQP中,咱們可使用默認的交換器和默認的綁定器,假設咱們的消息隊列名爲「app.svc01」,咱們下面的僞代碼來建立共享隊列:

Queue.Delcare
queue=app.svc01
exclusive=FALSE

可能會有多個消費者使用這個共享隊列,假設每一個消費者都用下面的僞代碼消費隊列中的消息:

Message.Subscribe
queue=app.svc01

爲了向共享隊列發佈消息,每一個生產者用下面的僞代碼向交換器發送消息。

Message.Transfer
routing_key=app.svc01
2.5.2.  構造回覆隊列

回覆隊列一般屬於臨時隊列,它們也一般屬於私有隊列,也就是說它們只被某一個訂閱者使用。除了這些特色,回覆隊列使用和標準隊列相同的匹配規則,所以咱們一樣可使用默認交換器。爲了不不一樣的客戶端使用的臨時隊列的名字衝突,建議客戶端在隊列名中包含一個全局惟一標識符(在RFC-4122中定義)或者其餘全局惟一標識符。

客戶端使用下面的僞代碼建立一個回覆隊列:

Queue.Declare
queue=tmp.550e8400-e29b-41d4-a716-446655440000
exclusive=TRUE
auto_delete=TRUE

爲了向回覆隊列發佈消息,生產者用下面的僞代碼向默認交換器發送消息:

Message.Transfer
routing_key=tmp.550e8400-e29b-41d4-a716-446655440000
2.5.3.  構造發佈訂閱隊列

在經典消息中間件中,單詞「訂閱」的意義有點模糊,它至少涉及到兩個不一樣的概念:一組匹配消息的規則和存儲匹配消息的臨時隊列。AMQP將這些工做劃分開,由綁定器和消息隊列共同完成。

經過匹配主題、消息字段或者消息內容等不一樣方式,發佈訂閱隊列從多個不一樣的消息源收集消息。發佈訂閱隊列和有名或回覆隊列之間的關鍵區別在於:發佈訂閱隊列的名稱並不用於路由,它採用抽象的匹配規則完成路由操做,而不是經過路由關鍵字與隊列名一對一匹配的方式。

讓咱們來看看什麼是發佈訂閱主題樹以及如何實現它。咱們須要一個交換器類型可以在主題樹上作匹配操做。在AMQP規範中,這種類型是主題交換器類型。主題交換器用相似於「STOCK.USD.*」的通配符擴展綁定關鍵字來匹配相似於「STOCK.USD.*」的路由關鍵字。

咱們不能使用默認交換器或綁定器,由於它們不支持主題式路由。所以咱們顯式建立一個綁定器。下面這段僞代碼建立和綁定一個發佈訂閱隊列:

Queue.Declare
queue=tmp.2
auto_delete=TRUE
Exchange. Bind
exchange=amq.topic
TO
queue=tmp.2
WHERErouting_key=STOCK.USD.*

一旦綁定器被建立,消息將從交換器路由到消息隊列,然而,消費者必須從隊列中消費消息:

Message.Subscribe
queue=tmp.2

爲了向發佈訂閱隊列發佈消息,生產者用下面的僞代碼發送消息

Message.Transfer
exchange=amq.topic
routing_key=STOCK.USD.IBM

主題式交換器使用它的綁定列表來匹配消息中的路由關鍵字(「STOCK.USD.IBM」),一旦匹配成功,它將消息路由到訂閱隊列中。

2.6.  消息

消息是路由和入隊原子單位。消息由消息頭和消息體組成,其中消息頭包含一組明肯定義的屬性,消息體是一段對於隊列而言不透明的二進制數據。

消息能夠是持久的——就算是遇到網絡故障、服務器崩潰和服務器過載等一系列問題,服務器也會將持久消息安全的保存在硬盤中,而且保證這些消息會被傳輸給客戶端。

消息能夠有優先級,在同一個消息隊列中的高優先級消息可能會比低優先級的消息更早被髮送給客戶端。當消息必須被丟棄時,服務器會先丟棄低優先級消息。

服務器不會更改消息體,可是可能會在轉發消息給消費者應用程序以前更改某些消息頭屬性。

2.6.1.  流控制

根據接收方的可用資源,流控制能夠被用來匹配消息的傳輸速率。接收者多是從客戶端接收消息的AMQP服務器,也多是從服務器消息隊列中接收消息的客戶端。這兩種狀況都採用一樣的流控制機制。流控制通常採用信用度的概念來表示發送者還能發送多少消息或者多少字節數據,當發送消息或者數據後,信用度下降,當接收者釋放被佔用的資源後,信用度提升。預取緩衝區能夠被接收者用來減小延遲。

2.6.2.  傳輸響應

當消息被接收時,消息接收者向發送者發回一個信號。當客戶端向服務器發送一條消息時,服務器向客戶端發回一個接受消息,代表服務器已經成功將消息路由到隊列中。當服務器向客戶端發送一條消息時,客戶端向服務器發回一個接受消息,代表客戶端已經成功處理了該消息,並通知服務器從隊列中刪除該消息。AMQP規範支持兩個不一樣的接受模式:

顯式,接收應用程序必須爲其接收到的每條消息或者每批消息向發送者發回一條接受消息。 None(TODO:在AMQP中,有accept-mode和acquire-mode,它們之間互相影響),認爲消息被髮送出去時就已經被接受了。

2.7.  訂閱

咱們使用單詞「訂閱」來表示實體:控制某個客戶端應用程序如何接收隊列中的消息。這和發佈訂閱消息傳輸中的訂閱者概念並不衝突。當客戶端「啓動一個訂閱」,它在服務器上建立一個訂閱實體。當客戶端「取消一個訂閱」,它在服務器上銷燬一個訂閱實體。

訂閱屬於單獨的客戶端會話,並致使消息隊列將消息異步的發送給客戶端。

2.8.  事務

AMQP規範定義了兩種大相徑庭的事務模型,單階段提交事務模型(稱爲tx)和兩階段提交事務模型(稱爲dtx)。標準的單階段提交事務模式的做用域爲單個會話,客戶端能夠選擇會話是不是事務性的(使用tx.select命令),一旦選擇事務性會話,會話會一直保持事務性直到它被銷燬。

一旦選擇事務性會話,由客戶端發出的全部指示會話傳輸和接受消息的命令只會在發出tx.commit命令以後生效。其餘改變服務器狀態的命令並不是事務性命令,所以也沒法回滾,好比聲明隊列和交換器的命令就是非事務性命令。

若是AMQP客戶端在一個事務中向服務器發佈一條消息(使用message.transfer命令),而後消息會被交換器路由到隊列中,直到這個事務完成以後纔會從隊列中被傳遞給其餘端點。服務器在消息被髮送的時候(而非事務被提交的時候)就決定消息是否能被路由到隊列中。服務器拒絕接受某條消息不會致使事務回滾,也不會等到commit命令生效的時候才執行,而是在消息被髮送到服務器上的時候就當即執行。

事務回滾對服務器所形成的影響是:客戶端發出的發佈和接受的命令都會被丟棄。須要注意的是獲取消息的命令並不是事務性操做,所以在事務做用域中的客戶端仍然能夠獲取消息。這意味着事務回滾以後,客戶端仍然持有全部在事務中服務器傳遞給它的消息(不管客戶端是否已接受)。若是客戶端但願服務器可以從新分發這些消息,它必須發出對應消息的釋放命令。(事務回滾時,消息的狀態是acquired,見2.6.2節,此時若是但願服務器可以從新分發這些消息,必須發出message.release的命令)

2.9.  分佈式事務

分佈式事務支持X-Open XA架構。

dtx類被用來限定和協調事務。dtx.start和dtx.end命令限定在會話中一個AMQP事務的範圍。事務的協調和恢復功能由其餘dtx類中的命令提供。

OMG OTS和JTS/JTA模型依賴於「資源管理器客戶端」實例,這個實例提供了操做全局事務中服務器資源的XA接口的實現。這些資源管理客戶端實例由Rmid惟一標識,這個標識貫穿c/c++中的xa_switch或者java中的XAResource的使用過程。

以下圖所描述的,一個資源管理器使用XA接口來限定事務的範圍和協調事務的結果。當資源管理器客戶端使用dtx.start和dtx.end命令參與到會話中的某個事務時,應用程序才能以事務性的方式發送和接收消息。資源管理器客戶端使用dtx的相關命令來協調事務結果和恢復AMQP服務器的操做。圖中的協調會話就是爲了這個目的。

2.9.1.  分佈式事務場景

下圖展現了應用程序以事務方式從隊列Q1消費消息的場景(經過事務管理器TM使用事務T1)。根據消費到的消息,應用程序使用數據庫管理系統更新數據庫表Tb,而後以事務方式向Q2發送一條消息。

 
2010年01月31日於7:49 上午

如下是我讀後的一些翻譯。一家之言,請斧正。

原譯文:私有隊列或共享隊列,持久存儲隊列或臨時存儲隊列,持久隊列或臨時隊列(durable修飾消息存儲,permanent修飾隊列,咋翻譯?)
個人翻譯:私有隊列或共享隊列,持久化存儲隊列或臨時存儲(如存儲於內存中)隊列,永久隊列或臨時隊列

原譯文:對於主題發佈訂閱路由,綁定關鍵字是主題階層值
個人翻譯:對於主題發佈訂閱路由,綁定關鍵字是該主題自精向粗逐級的關鍵字

原譯文:當消息隊列將消息提交給訂閱者以後(TODO:can deliver和提交以後貌似不一樣,我理解錯了嗎?),它將消息從內部緩衝區刪除。
個人翻譯:對於可被送達的消息,它將消息從內部緩衝區刪除。

原譯文:直接將消息發送到消息隊列會破壞AMQP模型內在的抽象性(TODO:the abstraction in the AMQP Model)
個人翻譯同樣。

原譯文:交換器(TODO:Exchanges are named on a per-virtual host basis)
個人翻譯:對於每一個虛擬主機內部,交換器有獨一無二的名字。

原譯文:扇出式交換器類型(TODO:fanout如何翻譯?)
個人翻譯:廣播式交換器類型

原譯文:流控制能夠被用來比較接收者中保存消息的資源佔用率。(TODO:Flow control may be used to match the rate at which messages are sent to the available resources at the receiver.)
個人翻譯:根據接收方的可用資源,流控制能夠被用來匹配消息的傳輸速率。

2010年01月31日於4:48 下午

一、永久隊列或臨時隊列,3ks
二、這裏的主題的層級有點問題,參考規範中的解釋,層級式的主題名示例:asia.china.stock.com1,asia.china.com2,以小數點分隔的層次關係對主題進行了分類
三、可被送達的消息,3ks
四、無
五、交換器有獨一無二的名字,3ks
六、廣播式交換器類型,3ks
七、比原翻譯要通順不少…
很是感謝您的留言。

2010年02月3日於12:35 上午

我也翻譯一段吧,有些地方翻得很差,請各位提出來。

3.1 Session定義
Session 是AMQP對等端之間的命名的交互,session 名侷限於一個認證機構(authentication principal),而且session名字由應用層程序來決定。在參與交互的對端之一,或者二者上可能保存session的狀態。發佈一個消息,建立一個隊列,或者選擇一個事務模式的命令必須發生在一個session的context以內。
Session是AMQP其餘部分的基礎。

Session 能夠被看作:
AMQP內建的恰好一次遞交操做的context
網絡協議映射和model層之間的接口
諸於隊列,交換器,訂閱這些實體的生命週期的一個範圍域
命令標識符的一個範圍域

3.1.1 session 生命期
Session 不是顯式地被建立或者被摧毀,在某種意義上,session 一直存在。對等端必須試着去附着(attach)到它的對端的session上,而不是去建立一個session。而後,這個附着請求的接收者會去查看它是否正持有該session的狀態。

對端雙方在附着到一個session上,它們必須保留session的相關狀態。當session分離了(無論是經過顯式的分離請求,仍是對等端之間的網絡鏈接斷開),那麼session的狀態還會被保留一段時間,這個時間是由先前對等端雙方協定好的。

3.1.2 命令傳輸
AMQP模型的交互是經過在對等端之間發送」命令」。這些命令高效地在session上發送。當一個命令從model層到session時,它被授予一個標識符。這些標識符可以用來把命令和其結果關聯起來,或者在異步AMQP命令流上執行同步。

3.1.3 session 做爲一個層次
Session 充當了網絡協議映射層和model層之間的接口。尤爲是,當對等端雙方都保留session的狀態時,它能夠被用來做爲一個機制,保證命令恰好遞交一次。
Session state 至少由以下組成:
一個replay 緩存區,存放對等端尚未確認收到的整個命令,或者命令的一部分
一個冪等的柵欄 – 一組命令標識符,對等端知道這些命令已經接收到了,可是不能肯定對方是否是會重發。

由於session名是由應用層程序指定的,除了這裏詳細說明的狀態以外,可能還有其餘更多的狀態。這些額外的狀態可能(例如)在session狀態過時是,會被用來執行恢復。然而,在這章,當咱們談到session狀態,咱們將只會指session層持有的那些狀態。

3.2 session 的功能
Session 層提供了幾個關鍵的服務,model層構建在這些服務之上:
命令順序化標識
將要執行命令的確認
命令完成時發通知
網絡失敗的重放,恢復
對端失敗後,狀態協調

3.2.1 順序化的標識
對等端發出的每一個命令必須被標識,爲了在整個系統內,能保證命令恰好一次執行。
Session層使用一個順序編號的機制來標識每一個命令,使得命令在一個session內是惟一的。

標識這個概念,使得能夠異步地把命令和起結果關聯起來。Model層能夠看到命令的標識符。當一個命令的結果返回時,能夠用命令標識符來關聯到是哪一個命令的執行結果。

3.2.2 確認
爲了使對等端可以安全地丟棄一個給定命令的狀態,它必須接收到一個該命令將會被執行的保證。更精確地說,發送者必須接收到一個確認該命令已經被執行,或者它的遞交被保留到指望的時間長度。

實際上,你可能會經過一個消息傳輸系統發送兩種類型的消息:持久消息和瞬間消息。對於瞬時消息,通常來講,消息傳輸系統和應用程序之間的協定是,消息可能在消息傳輸系統丟失瞬時狀態時,消息可能會被丟失。對於一個持久消息,消息傳輸系統必須保證消息被保存在最持久的的存儲中。

Session 層處理消息確認的發送和接收。這使得session層能夠管理它須要持有的狀態,可以在對等端臨時失敗時,或者傳輸失敗時,經過這些狀態可以進行恢復。

確承認以批量或者不肯定地延遲。尤爲是若是一個對等端不須要緊急的確認通知,確承認以被忽略掉,由於它僅僅是意味着一個命令的完成。

3.2.3 命令完成
從確認概念獨立出來的是命令完成概念。爲了同步和確保不一樣session間的徹底有序化的目的,所以頗有必要在一個命令執行完成時通知到對等端。

在對等端沒有請求緊急完成通知的地方,好比通知能夠延遲或者能夠批量發送,這適用於一命令範圍。這減少了網絡的流量。

例如,若是3個隊列按順序聲明,如命令1到3。服務器可能會像以下這下通知命令完成

注意,命令的接收方將會發送整個已經完成的命令集(這裏不明白啥意思,比較難翻)

3.2.4 重放和恢復
通常地,AMQP系統應該可以處理臨時的網絡失敗,或者AMQP 服務器cluster 中的單點失敗。爲了可以從這些失敗中倖存,session必須用來重放在失敗點接收有疑問的命令。Session 層提供必要的工具來標識有疑問的命令集,而且在無重複遞交風險的狀況下重放這些命令。

2010年02月3日於5:25 下午

google group已經被屏蔽了,若是誰有興趣的話能夠到這個地址來參與amqp的討論:http://n3.nabble.com/AMQP-f185611.html

 

http://blog.csdn.net/puncha/article/details/8450909
相關文章
相關標籤/搜索