<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 41  文章 - 7  trackbacks - 0
    <2016年8月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    常用鏈接

    留言簿

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    1 概述
    1.1 本文檔的目標(biāo)
    此文檔定義了一個(gè)網(wǎng)絡(luò)協(xié)議-高級(jí)消息隊(duì)列協(xié)議(AMQP), 它使一致的客戶端程序可以與一致的消息中間件服務(wù)器進(jìn)行通信.
    我們面對(duì)的是這個(gè)領(lǐng)域有經(jīng)驗(yàn)的技術(shù)讀者,同時(shí)還提供了足夠的規(guī)范和指南.技術(shù)工程師可以根據(jù)這些文檔,在任何硬件平臺(tái)上使用各種編程語(yǔ)言來(lái)構(gòu)建遵從該協(xié)議的解決方案。
    1.2 摘要
    1.2.1 為什么使用AMQP?
    AMQP在一致性客戶端和消息中間件(也稱為"brokers")之間創(chuàng)建了全功能的互操作.
    我們的目標(biāo)是實(shí)現(xiàn)一種在全行業(yè)廣泛使用的標(biāo)準(zhǔn)消息中間件技術(shù),以降低企業(yè)和系統(tǒng)集成的開(kāi)銷,并且向大眾提供工業(yè)級(jí)的集成服務(wù)。
    我們的宗旨是通過(guò)AMQP,讓消息中間件的能力最終被網(wǎng)絡(luò)本身所具有,并且通過(guò)消息中間件的廣泛使用發(fā)展出一系列有用的應(yīng)用程序.
    1.2.2 AMQP范圍
    為了完全實(shí)現(xiàn)消息中間件的互操作性,需要充分定義網(wǎng)絡(luò)協(xié)議和消息代理服務(wù)的功能語(yǔ)義。
    因此,AMQP通過(guò)如下來(lái)定義了網(wǎng)絡(luò)協(xié)議(AMQP是協(xié)議!)和服務(wù)端服務(wù):
    1. 一套確定的消息交換功能,也就是“高級(jí)消息交換協(xié)議模型”。AMQP模型包括一套用于路由和存儲(chǔ)消息的功能模塊,以及一套在這些模塊之間交換消息的規(guī)則。
    2. 一個(gè)網(wǎng)絡(luò)線級(jí)協(xié)議(數(shù)據(jù)傳輸格式),AMQP促使客戶端可使用AMQ模型來(lái)與服務(wù)器交互.
    可以只實(shí)現(xiàn)AMQP協(xié)議規(guī)范中的的部分語(yǔ)義,但是我們相信這些明確的語(yǔ)義有助于理解這個(gè)協(xié)議。
    1.2.3 高級(jí)消息隊(duì)列模型(AMQ 模型)
    我們需要明確定義服務(wù)器語(yǔ)義,因?yàn)樗蟹?wù)器實(shí)現(xiàn)都應(yīng)該與這些語(yǔ)義保持一致性,否則就無(wú)法進(jìn)行互操作. 因此AMQ 模型定義了一系列模塊化組件和標(biāo)準(zhǔn)規(guī)則來(lái)進(jìn)行協(xié)作. 有三種類型的組件可以連接服務(wù)器處理鏈來(lái)創(chuàng)建預(yù)期的功能:
    1. "交換器(exchange)" :接收來(lái)自發(fā)布者應(yīng)用程序的消息,并基于任意條件(通常是消息屬性和內(nèi)容)將這些消息路由到消息隊(duì)列(message queues).
    2."消息隊(duì)列(message queue)":存儲(chǔ)消息直到它們可以被消費(fèi)客戶端應(yīng)用程序(或多線程應(yīng)用程序)安全處理.
    3."綁定(binding)":定義了消息隊(duì)列與交換器之間的關(guān)系,并提供了消息路由條件.
    使用這些模型我們可以很容易地模擬經(jīng)典的存儲(chǔ)轉(zhuǎn)發(fā)隊(duì)列和面向消息中間件的主題訂閱概念. 我們還可以表示更為復(fù)雜的概念,例如:基于內(nèi)容的路由,工作負(fù)載分配和按需消息隊(duì)列。
    大致上講, AMQP 服務(wù)器類似與郵件服務(wù)器, 每個(gè)交換器都扮演了消息傳送代理,每個(gè)消息隊(duì)列都作為郵箱,而綁定則定義了每個(gè)傳送代理中的路由表.發(fā)布者發(fā)送消息給獨(dú)立的傳送代理,然后傳送代理再路由消息到郵箱中.消費(fèi)者從郵箱中收取消息. 相比較而言,在AMQP之前的許多中間件系統(tǒng)中,發(fā)布者直接發(fā)送消息到獨(dú)立收件箱(在存儲(chǔ)轉(zhuǎn)發(fā)隊(duì)列的情況下),或者發(fā)布到郵件列表中 (在主題訂閱的情況下).
    區(qū)別就在于用戶可以控制消息隊(duì)列和交換器之間的綁定規(guī)則,這可以做很多有趣的事情,比如定義一條規(guī)則:“將所有包含這樣消息頭的消息都復(fù)制一份再發(fā)送到消息隊(duì)列中”。
    AMQ模型是基于下面的需求來(lái)驅(qū)動(dòng)設(shè)計(jì)的:
    1. 支持與主要消息產(chǎn)品相媲美的語(yǔ)義。.
    2. 提供與主要消息產(chǎn)品相媲美的性能水平.
    3. 允許通過(guò)應(yīng)用程序使用服務(wù)器特定語(yǔ)義來(lái)編程.
    4.靈活性,可擴(kuò)展性,簡(jiǎn)單性
    1.2.4 高級(jí)消息隊(duì)列協(xié)議(AMQP)
    AMQP協(xié)議是具有現(xiàn)代特征的二進(jìn)制協(xié)議: 它是多通道的, 協(xié)商的,異步的,安全的,便攜的,自然的,高效的。 AMQP通常劃分成兩層:


    功能層( functional layer)定義了一系列命令(分成功能獨(dú)立的邏輯類),可為應(yīng)用程序做有用工作。
    傳輸層,將這些方法從應(yīng)用程序應(yīng)用搬到服務(wù)器并返回,它同時(shí)會(huì)處理通道復(fù)用,幀同步, 內(nèi)容編碼,心跳檢測(cè), 以及數(shù)據(jù)表示和錯(cuò)誤處理.
    在不改變協(xié)議可視功能的前提下,可使用任意的傳輸協(xié)議來(lái)替換傳輸層.也可以將同一個(gè)傳輸層用于不同的高級(jí)協(xié)議.
    AMQ模型是基于下面需求驅(qū)動(dòng)的:
     為了保證一致性實(shí)現(xiàn)之間的互操作性。.
     提供服務(wù)質(zhì)量的顯式控制.
     一貫的、明確的命名.
     通過(guò)協(xié)議允許服務(wù)器完全可配置.
     使用命令標(biāo)記法可輕易地映射到應(yīng)用程序級(jí)別API.
     一目了然,每個(gè)操作都在做自己的事情。
    AMQP傳輸層的設(shè)計(jì)是由以下需求驅(qū)動(dòng)的(沒(méi)有特定順序):
     堅(jiān)實(shí)的,使用二進(jìn)制編碼來(lái)打包和解包.
     處理任何大小的消息,沒(méi)有明顯限制(實(shí)際上有限制).
     在單個(gè)連接上攜帶攜帶多個(gè)通道.
     長(zhǎng)時(shí)間生存的,沒(méi)有顯著的內(nèi)建限制。
     允許異步命令在管道中排隊(duì).
     易于擴(kuò)展,以處理新的更新的需求。
     與未來(lái)版本兼容。
     可修復(fù),使用一個(gè)強(qiáng)大的斷言模型。
     對(duì)編程語(yǔ)言保持中立。
     適合代碼擴(kuò)展過(guò)程。
    1.2.5 規(guī)模化部署

    AMQP范圍涵蓋不同等級(jí)規(guī)模,大致如下:
     開(kāi)發(fā)/臨時(shí)使用: 1臺(tái)服務(wù)器, 1個(gè)用戶, 10個(gè)消息隊(duì)列,每秒 1個(gè)消息.
     產(chǎn)品應(yīng)用程序: 2服務(wù)器, 10-100個(gè)用戶, 10-50個(gè)消息隊(duì)列,每秒10個(gè)消息(36Kmessages/hour).
     部門任務(wù)關(guān)鍵應(yīng)用: 4 臺(tái)服務(wù)器, 100-500個(gè)用戶, 50-100 個(gè)消息隊(duì)列, 每秒100個(gè)消息(360K/hour).
    區(qū)域任務(wù)關(guān)鍵應(yīng)用: 16 臺(tái)服務(wù)器, 500-2,000 個(gè)用戶, 100-500 個(gè)消息隊(duì)列和主題,
    每秒1000個(gè)消息(3.6M/hour).
     全球任務(wù)關(guān)鍵應(yīng)用: 64 臺(tái)服務(wù)器, 2K-10K 個(gè)用戶, 500-1000 個(gè)消息隊(duì)列和主題,
    每秒10,000 個(gè)消息(36M/hour).
     市場(chǎng)數(shù)據(jù)(交易): 200 臺(tái)服務(wù)器, 5K 個(gè)用戶, 10K 主題, 第秒100K個(gè)消息(360M/hour).
    規(guī)模越大,消息傳輸延遲就越重要.例如,市場(chǎng)數(shù)據(jù)變化相當(dāng)快. 實(shí)現(xiàn)可以依據(jù)不同的服務(wù)質(zhì)量和管理能力不區(qū)分對(duì)待,但必須與本規(guī)范兼容.
    1.2.6 功能范圍
    我們要支持多種消息傳遞架構(gòu):
     使用多個(gè)writers和一個(gè)reader來(lái)存儲(chǔ)轉(zhuǎn)發(fā).
     使用多個(gè)writers和多個(gè)readers來(lái)分散工作負(fù)載.
     使用多個(gè)writers和多個(gè)readers來(lái)發(fā)布訂閱
     使用多個(gè)writers和多個(gè)readers來(lái)基于內(nèi)容路由.
     使用多個(gè)writers和多個(gè)readers來(lái)進(jìn)行隊(duì)列文件傳輸.
     在兩個(gè)節(jié)點(diǎn)之間進(jìn)行點(diǎn)對(duì)點(diǎn)連接.
     使用多個(gè)源和多個(gè)readers來(lái)分布市場(chǎng)數(shù)據(jù).
    1.3 文檔組織
    文檔分成五個(gè)章節(jié), 其中大部分設(shè)計(jì)為可按你的興趣來(lái)獨(dú)立閱讀:
    1. "概述" (本章). 讀本章來(lái)了解介紹.
    2. "總體架構(gòu)",這章中我們描述了架構(gòu)和AMQP總體設(shè)計(jì). 本章的目的是幫助系統(tǒng)架構(gòu)師了解AMQP如何工作的.
    3. "功能說(shuō)明", 這章中我們定義了應(yīng)用程序如何與AMQP一起協(xié)同工作. 本章先講述了一個(gè)可讀性討論,其次是每個(gè)協(xié)議命令的詳細(xì)規(guī)范,以作為實(shí)施者參考。在閱讀本章之前,你應(yīng)該閱讀總體構(gòu)架.
    4. "技術(shù)說(shuō)明",這章中我們定義了AMQP傳輸層是如何工作的. 這章由簡(jiǎn)短討論和線路結(jié)構(gòu)的詳細(xì)說(shuō)明組成.你如果想線路級(jí)協(xié)議是如何工作的,可以閱讀本章.

    1.4 約定
    1.4.1 實(shí)現(xiàn)者指導(dǎo)方針
     我們使用了IETF RFC 2119中定義的術(shù)語(yǔ) MUST, MUST NOT, SHOULD, SHOULD NOT, 和 MAY.
     當(dāng)討論需要AMQP服務(wù)器的特定行為時(shí),我們使用術(shù)語(yǔ)"the server".
     當(dāng)討論需要AMQP客戶端的特定行為時(shí),我們使用術(shù)語(yǔ)"the client".
     我們使用術(shù)語(yǔ)"the peer" 來(lái)代表服務(wù)器或客戶端.
     如果沒(méi)有指示,數(shù)字值是十進(jìn)制的.
     Protocol常量是以大寫名稱表示. AMQP實(shí)現(xiàn)應(yīng)當(dāng)在定義,源碼,以及文檔中使用這些名稱.
     屬性名稱,方法名稱,以及幀字段是以小寫名稱來(lái)表示. AMQP實(shí)現(xiàn)應(yīng)當(dāng)在定義,源碼,以及文檔中使用這些名稱.
     AMQP中的字符串是區(qū)分大小寫的.例如, "amq.Direct"與"amq.direct”是兩個(gè)不同的交換器.
    1.4.2 版本編號(hào)方式
    AMQP版本使用兩個(gè)或三個(gè)數(shù)字進(jìn)行表示 – 主版本號(hào),次版本號(hào)以及可選的修訂版本號(hào).為了方便,版本號(hào)表示為:major-minor[-revision] 或major.minor[.revision]:
     官方說(shuō)明中,major, minor, 和revision均支持0到99的數(shù)字.
     Major, minor, 和 revision 中100及其以上的數(shù)字保留用于內(nèi)部測(cè)試和開(kāi)發(fā).
     版本號(hào)表明了語(yǔ)法和語(yǔ)義互操作性。
     版本 0-9-1 表示 major = 0, minor = 9, revision = 1.
     1.1版本表示為major = 1, minor = 1, revision = 0. AMQP/1.1等價(jià)于AMQP/1.1.0或AMQP/1-1-0.

    1.4.3 技術(shù)術(shù)語(yǔ)
    這些術(shù)語(yǔ)在本文檔的上下文中有特殊的意義:
     AMQP 命令架構(gòu)(AMQP command architecture): 用于在AMQ模型架構(gòu)上執(zhí)行操作的線級(jí)協(xié)議命令.
     AMQ模塊架構(gòu)(AMQ model architecture): 表示關(guān)鍵實(shí)體和語(yǔ)義的邏輯框架,它必須對(duì)兼容AMQP實(shí)現(xiàn)的服務(wù)器可用, 使得服務(wù)器的狀態(tài)可以通過(guò)客戶端按本規(guī)范中定義的語(yǔ)義來(lái)實(shí)現(xiàn).
     Connection: 網(wǎng)絡(luò)連接,如.一個(gè)TCP/IP socket連接.
     Channel: 兩個(gè)AMQP節(jié)點(diǎn)之間雙向通信流. 通道是多路復(fù)用的,因此單個(gè)網(wǎng)絡(luò)連接可以支撐多個(gè)通道
     Client: AMQP連接或通道的發(fā)起人. AMQP不是對(duì)稱的.客戶端生產(chǎn)和消費(fèi)消息,而服務(wù)器端入列和路由消息.
     Server:接受客戶端連接,實(shí)現(xiàn)AMQP消息隊(duì)列和路由功能的過(guò)程.也稱為"broker".
     Peer: AMQP連接中任意一方.AMQP連接明確包含兩個(gè)節(jié)點(diǎn)(一個(gè)是client, 一個(gè)是server).
     Frame: 一個(gè)正式定義的連接數(shù)據(jù)包。框架總是連接寫和讀數(shù)據(jù)包-作為連接上的一個(gè)單元。
     Protocol class: 用于處理特定類型功能的AMQP命令集合 (也稱為方法).
     Method: 用于在節(jié)點(diǎn)之間傳遞特定類型的AMQP命令幀.
     Content: 服務(wù)器和應(yīng)用程序之間傳送的數(shù)據(jù).這個(gè)術(shù)語(yǔ)是“message”的同義詞。
     Content header:描述內(nèi)容屬性特定類型幀.
     Content body: 包含原始應(yīng)用程序數(shù)據(jù)的特定類型幀.內(nèi)容體幀完全不透明-服務(wù)器不以任何方式檢查或修改其body內(nèi)容.
     Message: 與Content同義.
     Exchange: 服務(wù)器中接收來(lái)自生產(chǎn)者應(yīng)用程序的消息的實(shí)體,并可選擇將這些消息路由到服務(wù)器中的消息隊(duì)列.
     Exchange type: 交換器特定模型的算法和實(shí)現(xiàn).而"交換器實(shí)例"是服務(wù)器中用于接收和路由消息的實(shí)體.
     Message queue: 保存消息并將它們轉(zhuǎn)發(fā)給消費(fèi)者應(yīng)用程序的命名實(shí)體。
     Binding: 用于創(chuàng)建消息隊(duì)列和交換器綁定關(guān)系的實(shí)現(xiàn).
     Routing key: 一個(gè)虛擬地址,虛擬機(jī)可用它來(lái)確定如何路由一個(gè)特定消息.
     Durable: 服務(wù)器資源可在服務(wù)器重啟時(shí)恢復(fù).
     Transient: 服務(wù)器資源或消息會(huì)在服務(wù)器重啟后擦除或重置.
     Persistent: 服務(wù)器存儲(chǔ)在可靠的磁盤存儲(chǔ)上的消息,并且在服務(wù)器重新啟動(dòng)后不丟失.
     Consumer: 從消息隊(duì)列中請(qǐng)求消息的客戶端應(yīng)用程序.
     Producer: 發(fā)布消息到交換器中的客戶端程序.
     Virtual host: 交換器,消息隊(duì)列以及相關(guān)對(duì)象的集合. 虛擬主機(jī)是共享同一個(gè)身份驗(yàn)證和加密環(huán)境的獨(dú)立服務(wù)器域。
     Assertion: 一個(gè)必須為true且可繼續(xù)執(zhí)行的條件.
     Exception: 一個(gè)失敗的斷言,可通過(guò)Channel或Connection來(lái)關(guān)閉.
    在AMQP中這些術(shù)語(yǔ)沒(méi)有特殊意義:
     Topic: 通常是分發(fā)消息的一種手段; AMQP使用一個(gè)或多個(gè)交換器類型來(lái)實(shí)現(xiàn)topics.
     Subscription:通常是從topics中接收數(shù)據(jù)的請(qǐng)求, AMQP以消息隊(duì)列和綁定的方式來(lái)實(shí)現(xiàn)訂閱.
     Service: 通常與server一個(gè)含義. AMQP使用“server”來(lái)遵循IETF標(biāo)準(zhǔn)命名。
     Broker: 通常與server一個(gè)含義。AMQP使用術(shù)語(yǔ)“client”和“server"來(lái)遵循IETF標(biāo)準(zhǔn)術(shù)語(yǔ)。
     Router: 有時(shí)用來(lái)描述交換器的動(dòng)作.交換器也可以作為消息終點(diǎn), "router" 在網(wǎng)絡(luò)領(lǐng)域中有特殊意義,因此AMQP不會(huì)使用它.

    2 總體架構(gòu)
    2.1 AMQ 模塊架構(gòu)
    本節(jié)將講解了服務(wù)器語(yǔ)法,須標(biāo)準(zhǔn)化來(lái)保證AMQP實(shí)現(xiàn)之間可互操作的語(yǔ)義。
    2.1.1 主要實(shí)體
    下面的圖顯示了整體AMQ模型:



    我們可以總結(jié)一下中間件服務(wù)器是什么:它是一個(gè)接受消息的數(shù)據(jù)服務(wù)器,并主要做兩件事情,依據(jù)條件將消息路由給不同的消費(fèi)者,當(dāng)消費(fèi)者消費(fèi)速度不夠快時(shí),它會(huì)把消息緩存在內(nèi)存或磁盤上.
    在AMQP之前的服務(wù)器中,它們會(huì)通過(guò)實(shí)現(xiàn)了特定類型路由和緩存的龐大引擎來(lái)完成. AMQ模塊使用較小的模塊結(jié)合更多樣和穩(wěn)健的方案來(lái)實(shí)現(xiàn). 它把這些任務(wù)分成了兩個(gè)不同角色:
     交換器, 它接受來(lái)自生產(chǎn)者的消息并將它們路由到消息隊(duì)列.
     消息隊(duì)列, 它存儲(chǔ)消息消息并把它們轉(zhuǎn)發(fā)給消費(fèi)者應(yīng)用程序.
    在交換器和消息隊(duì)列之間有一個(gè)明顯的界面,稱為綁定(binding),我們隨后會(huì)進(jìn)行講解.
    AMQP提供了運(yùn)行時(shí)程序語(yǔ)義,主要有兩方面:
    1. 運(yùn)行時(shí)通過(guò)該協(xié)議可創(chuàng)建任意的交換器和消息隊(duì)列類型的能力(有些是在標(biāo)準(zhǔn)中定義的,但可以添加其他作為服務(wù)器擴(kuò)展)。
    2. 運(yùn)行時(shí)通過(guò)協(xié)議包裝交換器和消息隊(duì)列來(lái)創(chuàng)建任何需要的消息處理系統(tǒng)的能力.
    2.1.1.1 消息隊(duì)列(Message Queue)
    消息隊(duì)列用于在內(nèi)存或磁盤上存儲(chǔ)消息, 并將它們依次投遞給一個(gè)或多個(gè)消費(fèi)者應(yīng)用程序.消息隊(duì)列是消息存儲(chǔ)和分發(fā)的實(shí)體. 每個(gè)消息隊(duì)列是完全獨(dú)立的,且是一個(gè)相當(dāng)聰明的對(duì)象。
    消息隊(duì)列有多個(gè)屬性:私有的或共享的, 持久的或臨時(shí)的,客戶端命名的或服務(wù)器端命名的等等.
    通過(guò)選擇希望的屬性,我們可以使用消息隊(duì)列來(lái)實(shí)現(xiàn)傳統(tǒng)的中間件實(shí)體,如:
     共享存儲(chǔ)轉(zhuǎn)發(fā)隊(duì)列:它可以持有消息,并以round-robin方式在消費(fèi)者之間分發(fā)消息.存儲(chǔ)轉(zhuǎn)發(fā)隊(duì)列通常是在多個(gè)消費(fèi)者之間是持久化的.
     私有回復(fù)隊(duì)列:它可以持有消息,并把消息轉(zhuǎn)發(fā)給單個(gè)消費(fèi)者. 回復(fù)隊(duì)列通常是臨時(shí)的,服務(wù)端命名的,且對(duì)于某個(gè)消費(fèi)者來(lái)說(shuō)是私有的.
     私有訂閱隊(duì)列:它可持有來(lái)自不同訂閱源的消息,并將它們轉(zhuǎn)發(fā)給單個(gè)消費(fèi)者.
    訂閱隊(duì)列通常是臨時(shí)的,服務(wù)器端命名的,并對(duì)于某個(gè)消費(fèi)者來(lái)說(shuō)是私有的
    AMQP沒(méi)有定義這些類別:這些只是如何使用消息隊(duì)列的例子.創(chuàng)建如持久化,共享訂閱隊(duì)列的新實(shí)體沒(méi)什么意義.

    2.1.1.2 交換器(Exchange)
    交換器接收來(lái)自生產(chǎn)者應(yīng)用程序的消息,并將它們按照事先約定的規(guī)則路由到消息隊(duì)列中.
    這些預(yù)先約定的規(guī)則或條件稱為綁定. 交換器會(huì)與路由引擎匹配.
    也就是說(shuō),他們會(huì)檢查消息,并使用他們的綁定表來(lái)決定如何將這些消息轉(zhuǎn)發(fā)到消息隊(duì)列或其他交換器中。交換器永遠(yuǎn)不會(huì)存儲(chǔ)信息。“交換器”一詞是指一類算法或算法實(shí)例。
    更確切的說(shuō),我們談到了交換器類型和交換器實(shí)例.
    AMQP定義了許多交換器類型,它們覆蓋了常見(jiàn)消息路由分發(fā)的基礎(chǔ)類型. AMQP服務(wù)器提供了這些交換器的默認(rèn)實(shí)例.使用AMQP的應(yīng)用程序可額外創(chuàng)建它們自己的交換器實(shí)例.交換器類型是命名的,這樣創(chuàng)建交換器的應(yīng)用程序就可以告知服務(wù)器他們使用的交換器類型.
    交換器實(shí)現(xiàn)也可以是命名的,這樣應(yīng)用程序可指定如何綁定隊(duì)列來(lái)發(fā)布消息.
    交換器還可以做更多的消息路由.它們可作為服務(wù)器內(nèi)的智能路由代理,按需接受消息和生產(chǎn)消息. 交換器概念的目的是定義一套模型或標(biāo)準(zhǔn),使得可以合理地?cái)U(kuò)展AMQP服務(wù)器,因?yàn)榭蓴U(kuò)展性會(huì)對(duì)互操作產(chǎn)生影響.
    2.1.1.3 路由鍵 (Routing Key)
    在一般情況下,交換器會(huì)檢查消息的屬性,如,它的header字段,body內(nèi)容,并使用這些和其他來(lái)源中的數(shù)據(jù)來(lái)決定如何消息路由。
    在大多數(shù)簡(jiǎn)單情況下,交換器會(huì)檢查某個(gè)單一的鍵字段,我們稱之為“路由鍵”。
    路由鍵是一個(gè)虛擬地址,該虛擬地址可用來(lái)決定如何路由消息。
    對(duì)于點(diǎn)對(duì)點(diǎn)的路由,路由鍵通常是消息隊(duì)列的名稱。
    對(duì)于主題發(fā)布訂閱路由,路由鍵通常是topic層次結(jié)構(gòu)值。
    在更復(fù)雜的情況下,路由鍵可以是消息header字段和/或消息內(nèi)容的組合體。
    2.1.1.4 類比電子郵件
    如果我們做過(guò)一個(gè)類似的電子郵件系統(tǒng),那我們會(huì)看到AMQP概念就不再是激進(jìn)的:
    一個(gè)AMQP消息類似于電子郵件;
     消息隊(duì)列就像一個(gè)郵箱;
     消費(fèi)者是一個(gè)可讀取和刪除電子郵件的郵件客戶端;
    交換器類似于一個(gè)MTA (郵件傳輸代理),它會(huì)檢查電子郵件,并基于路由鍵和表來(lái)決定如何將電子郵件發(fā)送到一個(gè)或多個(gè)郵箱中;
     路由鍵對(duì)應(yīng)于電子郵件中To:,Cc: ,Bcc: 地址, 不包含服務(wù)端信息(路由完全是AMQP服務(wù)器內(nèi)部的行為);
     每個(gè)交換器實(shí)例類似于單獨(dú)的MTA過(guò)程,用于處理一些電子郵件子域名或特定類型的電子郵件傳輸;
     綁定類似于MTA路由表中的實(shí)體.
    AMQP的強(qiáng)大來(lái)自于創(chuàng)建隊(duì)列(郵箱),交換器(MTA過(guò)程),和綁定(路由實(shí)體)的能力,并可在運(yùn)行時(shí),將這些鏈接在一起,這遠(yuǎn)遠(yuǎn)超出了簡(jiǎn)單的"to" 地址到郵箱名稱的映射.
    我們不應(yīng)該把email與AMQP類比得太遠(yuǎn):它們之間有根本上的區(qū)別。AMQP面臨的挑戰(zhàn)是如何來(lái)存儲(chǔ)和轉(zhuǎn)發(fā)服務(wù)器中的消息,SMTP(IETF RFC 821)稱其為“自治系統(tǒng)”。而在電子郵件中的挑戰(zhàn)是自治系統(tǒng)之間如何路由消息。
    在一個(gè)服務(wù)器內(nèi)路由和在多個(gè)服務(wù)器之間路由,方式是不同的,應(yīng)該有不同的解決方案.
    在多個(gè)AMQP服務(wù)器(擁有不同實(shí)體)之間路由時(shí),必須明確建立不同的橋梁, 為達(dá)到在多個(gè)獨(dú)立實(shí)體之間傳送消息的目的,一個(gè)AMQP服務(wù)器必須作為另一個(gè)AMQP服務(wù)器的客戶端.這種工作方式很適合需要使用AMQP的業(yè)務(wù)類型,因?yàn)檫@些橋梁可以為業(yè)務(wù)流程,合同義務(wù)和安全問(wèn)題打下基礎(chǔ).
    2.1.2 消息流(Message Flow)
    下面的圖展示了通過(guò)AMQ模塊服務(wù)器的消息流:

    2.1.2.1 消息生命周期
    一個(gè)AMQP消息由一組屬性和不透明的內(nèi)容組成。一個(gè)新消息是由生產(chǎn)者應(yīng)用程序通過(guò)使用AMQP client API來(lái)創(chuàng)建的.生產(chǎn)者將“內(nèi)容”附著在消息中,并對(duì)其設(shè)置一些消息“屬性”。生產(chǎn)者使用路由信息來(lái)標(biāo)記消息,其表面上類似于地址,但幾乎可以創(chuàng)建任何模式。然后,生產(chǎn)者將消息發(fā)送到服務(wù)器上的交換器中。
    當(dāng)消息到達(dá)服務(wù)器時(shí),交換器通常會(huì)將消息路由到一級(jí)存在于服務(wù)器上的消息隊(duì)列中.如果消息不能路由,交換器會(huì)默默地丟棄或者將其返回給生產(chǎn)者. 生產(chǎn)者可以選擇如何來(lái)處理未路由消息.
    單個(gè)消息可存在于多個(gè)消息隊(duì)列. 服務(wù)器可以不同方式進(jìn)行處理,如通過(guò)拷貝消息或通過(guò)引用計(jì)數(shù)器等. 這不影響互操作性。然而,當(dāng)一個(gè)消息被路由到多個(gè)消息隊(duì)列時(shí),它在每個(gè)消息隊(duì)列上都是一樣的。沒(méi)有獨(dú)特的標(biāo)識(shí)符來(lái)區(qū)分不同的副本。
    當(dāng)消息到達(dá)消息隊(duì)列時(shí),消息隊(duì)列會(huì)通過(guò)AMQP,立即嘗試將消息傳遞給消費(fèi)者應(yīng)用程序.如果不行,消息隊(duì)列會(huì)存儲(chǔ)消息(按發(fā)布者要求存儲(chǔ)在內(nèi)存或磁盤中),并等待消費(fèi)者準(zhǔn)備好.如果沒(méi)有消費(fèi)者,消息隊(duì)列通過(guò)AMQP將消息返回給生產(chǎn)者(再次地,如果生產(chǎn)者對(duì)此有要求的話).
    當(dāng)消息隊(duì)列把消息投遞給消費(fèi)者后,它會(huì)從內(nèi)部緩沖區(qū)中刪除消息.這有可能立即發(fā)生,也有可能在消費(fèi)者應(yīng)答它已成功處理之后刪除.消費(fèi)者可選擇如何以及何時(shí)來(lái)應(yīng)答消息.同樣地, 消費(fèi)者也可以拒絕消息(一個(gè)否定應(yīng)答).
    生產(chǎn)者消息和消費(fèi)者應(yīng)答可以組成事務(wù). 當(dāng)一個(gè)應(yīng)用程序同時(shí)扮演兩種角色時(shí),通常它會(huì)做混合工作:發(fā)送消息和發(fā)送應(yīng)答,然后提交或回滾事務(wù).
    從服務(wù)器投遞消息給消費(fèi)者,這個(gè)過(guò)程不是事務(wù)的,它只能通過(guò)消息應(yīng)答來(lái)處理.
    2.1.2.2 生產(chǎn)者能看到什么
    通過(guò)與電子郵件系統(tǒng)的類比,我們可以看到生產(chǎn)者不能直接向消息隊(duì)列發(fā)送消息.
    如果允許這樣做,將會(huì)破壞AMQ模塊中的抽象. 這就像允許電子郵件繞過(guò)MTA的路由表,直接發(fā)送到郵箱中一樣. 這會(huì)導(dǎo)致在中間過(guò)程中不能插入過(guò)濾處理,例如,垃圾郵件檢測(cè).
    AMQ 模塊也使用了與電子郵件系統(tǒng)一樣的準(zhǔn)則:所有消息都發(fā)向單一的某個(gè)點(diǎn):交換器或MTA,然后這個(gè)點(diǎn)根據(jù)規(guī)則和隱藏在發(fā)送者中的信息來(lái)檢查消息,并將消息路由到落腳點(diǎn)(對(duì)于發(fā)送者來(lái)說(shuō),信息仍然是隱藏的).
    2.1.2.3 消費(fèi)者能看到什么
    當(dāng)我們站在消費(fèi)者角度來(lái)看與電子郵件系統(tǒng)的類比,這就開(kāi)始崩潰了(break down). Email客戶端是被動(dòng)的 - 它們可以讀取它們的郵箱,但它們不能對(duì)郵箱的收取產(chǎn)生任何影響.而AMQP消費(fèi)者也可以是被動(dòng)的,就像email客戶端一樣. 也就是說(shuō),我們可以編寫一個(gè)程序來(lái)希望特定消息隊(duì)列準(zhǔn)備好綁定, 并且應(yīng)用程序脫離消息隊(duì)列來(lái)簡(jiǎn)單處理消息(譯者注:不懂).
    此外,我們也允許AMQP 客戶端程序執(zhí)行下面的操作:
     創(chuàng)建或銷毀消息隊(duì)列;
     通過(guò)綁定來(lái)定義消息隊(duì)列填充的方式;
     選擇不同的交換器,這將完全改變路由語(yǔ)義.
    使用協(xié)議,這有點(diǎn)像電子郵件系統(tǒng)能做的:
     創(chuàng)建一個(gè)新郵箱;
     告訴MTA帶特定header字段的消息都可以拷貝到這個(gè)郵箱中;
     完全改變電子郵件系統(tǒng)解析地址和其它消息頭的方式
    我們看到AMQP更像是一種語(yǔ)言的連接片而非一個(gè)系統(tǒng).這正是目標(biāo)的一部分,通過(guò)協(xié)議來(lái)使服務(wù)器行為可編程化.

    2.1.2.4 原子模式
    大多數(shù)集成架構(gòu)不需要這個(gè)級(jí)別的復(fù)雜度.就像業(yè)余攝影師一樣,大多數(shù)AMQP用戶需要傻瓜式的模式. AMQP通過(guò)兩方面來(lái)簡(jiǎn)化了概念:
     針對(duì)消息生產(chǎn)者的默認(rèn)交換器;
     基于隊(duì)列名稱作為路由鍵來(lái)匹配默認(rèn)綁定.
    實(shí)際上,給予適當(dāng)?shù)臋?quán)限,默認(rèn)的綁定讓生產(chǎn)者直接發(fā)送消息到消息隊(duì)列–它模擬了傳統(tǒng)中間件中簡(jiǎn)單的“發(fā)送到目的地"的解決方案。
    默認(rèn)綁定不會(huì)阻止消息隊(duì)列更復(fù)雜方式的使用。然而它使得在不需要了解交換器和綁定如何工作的情況下,就可以使用AMQP.
    2.1.3 交換器
    2.1.3.1 交換器類型
    每種交換器類型都實(shí)現(xiàn)了某種路由算法.這里有許多標(biāo)準(zhǔn)的交換器類型(將在"功能說(shuō)明"章節(jié)中講解), 但有兩點(diǎn)是很重要的:
     基于路由鍵來(lái)路由的direct 交換器類型. 默認(rèn)交換器是direct交換器.
     基于路由模式來(lái)路由的topic 交換器類型.
    在啟動(dòng)時(shí),服務(wù)器將會(huì)創(chuàng)建一系列交換器,如direct 和topic交換器.
    2.1.3.2 交換器生命周期
    每個(gè)AMQP 服務(wù)器都預(yù)先創(chuàng)建了許多交換器(實(shí)例).這些交換器當(dāng)服務(wù)器啟動(dòng)時(shí)就存在了,不能被銷毀. AMQP 應(yīng)用程序也可以創(chuàng)建它們自己的交換器.AMQP不會(huì)使用像這樣的"create"方法,相反它使用 "declare"方法,其意義是:"如果你不存在就創(chuàng)建,否則繼續(xù)".這是合理的:應(yīng)用程序可以為了私有使用而創(chuàng)建交換器,并在完成工作時(shí)進(jìn)行銷毀. AMQP提供了方法來(lái)銷毀交換器,但一般來(lái)說(shuō),應(yīng)用程序不會(huì)這樣做.在本章我們的例子中,我們假設(shè)交換器已在服務(wù)器啟動(dòng)時(shí)創(chuàng)建過(guò)了. 我們不會(huì)展示聲明交換器的應(yīng)用程序.

    2.1.4 消息隊(duì)列
    2.1.4.1 消息隊(duì)列屬性
    當(dāng)客戶端程序創(chuàng)建了消息隊(duì)列時(shí),它可以選擇一些重要的屬性:
     name - 如果沒(méi)有指定,服務(wù)器會(huì)選擇一個(gè)名稱,并將其提供給客戶端.一般來(lái)說(shuō),當(dāng)應(yīng)用程序共享消息隊(duì)列時(shí),它們已經(jīng)對(duì)消息隊(duì)列名稱作了事先的約定,當(dāng)一個(gè)應(yīng)用程序需要出于其自身目的來(lái)要求隊(duì)列時(shí),它可讓服務(wù)器提供一個(gè)名稱.
     exclusive - 如果設(shè)置了,隊(duì)列將只屬于當(dāng)前連接,且在連接關(guān)閉時(shí)刪除.
     durable - 如果設(shè)置了, 消息會(huì)進(jìn)行存儲(chǔ),并在服務(wù)器重啟時(shí)激活. 當(dāng)服務(wù)器重啟時(shí),它可能會(huì)丟失瞬時(shí)消息.
    2.1.4.2 隊(duì)列生命周期
    這里主要有兩種消息隊(duì)列生命周期:
     持久化消息隊(duì)列:它們可被多個(gè)消費(fèi)者共享,并可獨(dú)立地存在- 即.不管是否有消費(fèi)者接收它們,它都可以繼續(xù)存在收集消息.
     臨時(shí)消息隊(duì)列:對(duì)某個(gè)消費(fèi)者是私有的,只能綁定到此消費(fèi)者.當(dāng)消費(fèi)者斷開(kāi)連接時(shí),消息隊(duì)列將被刪除.
    也存在一些變化,如共享消息隊(duì)列會(huì)在最后一個(gè)消費(fèi)才斷開(kāi)連接時(shí)刪除消息隊(duì)列.下面的圖展示了臨時(shí)消息隊(duì)列創(chuàng)建和刪除的過(guò)程:



    2.1.5 綁定
    綁定表示的是交換和消息隊(duì)列之間的關(guān)系,該關(guān)系告訴交換器如何路由消息。綁定是從客戶端應(yīng)用程序命令(一個(gè)擁有和使用消息隊(duì)列的應(yīng)用程序)中來(lái)綁到交換器上的。我們可以在偽代碼中表達(dá)一個(gè)綁定命令,如下所示:
    Queue.Bind <queue> TO <exchange> WHERE <condition>
    讓我們看一下三種典型使用情況: 共享隊(duì)列,私有回復(fù)隊(duì)列,發(fā)布訂閱.
    2.1.5.1 構(gòu)造共享隊(duì)列
    共享隊(duì)列是經(jīng)典的中間件"點(diǎn)對(duì)點(diǎn)隊(duì)列".在AMQP中,我們可使用默認(rèn)交換器和默認(rèn)綁定.我們假設(shè)消息隊(duì)列稱為"app.svc01". 這里是創(chuàng)建共享隊(duì)列的偽代碼:
    Queue.Declare
    queue=app.svc01
    在這個(gè)共享隊(duì)列中,我們有許多消費(fèi)者.要從共享隊(duì)列中消費(fèi), 每個(gè)消費(fèi)者可以這樣做:
    Basic.Consume
    queue=app.svc01
    要發(fā)送到共享隊(duì)列, 每個(gè)生產(chǎn)者都要將消息發(fā)布到默認(rèn)交換器:
    Basic.Publish
    routing-key=app.svc01
    2.1.5.2 構(gòu)建回復(fù)隊(duì)列
    回復(fù)隊(duì)列通常是臨時(shí)的,服務(wù)器分配名稱的. 它們通常也是私有的,即只能由單個(gè)消費(fèi)者讀取. 除了這些特殊情況外,回復(fù)隊(duì)列使用與標(biāo)準(zhǔn)隊(duì)列相同的匹配條件,因此我們也可以使用默認(rèn)交換器.
    下面是創(chuàng)建回復(fù)隊(duì)列的偽代碼, 這里的S:表示一個(gè)服務(wù)器回復(fù):
    Queue.Declare
    queue=<empty>
    exclusive=TRUE
    S:Queue.Declare-Ok
    queue=tmp.1
    要發(fā)布到回復(fù)隊(duì)列,生產(chǎn)者需將消息發(fā)送到默認(rèn)交換器中:
    Basic.Publish
    exchange=<empty>
    routing-key=tmp.1
    有一個(gè)標(biāo)準(zhǔn)消息屬性-Reply-To, 它專門設(shè)置用來(lái)攜帶回復(fù)隊(duì)列的名稱.
    2.1.5.3 構(gòu)建Pub-Sub 訂閱隊(duì)列
    在經(jīng)典中間件中,術(shù)語(yǔ)"訂閱(subscription)" 在概念上是模糊的,它至少涉及了兩個(gè)不同的概念: 匹配消息的條件和用于保存匹配消息的臨時(shí)隊(duì)列. AMQP把這個(gè)工作分成了綁定和消息隊(duì)列兩個(gè)部分.在AMQP中沒(méi)有稱為訂閱的實(shí)體.
    讓我們來(lái)描述pub-sub訂閱:
     為單個(gè)消費(fèi)者(或某些情況下,多個(gè)消費(fèi)者)保存消息
     通過(guò)一系列匹配主題,消息字段或內(nèi)容的不同綁定方式來(lái)從多個(gè)源中收集消息
    訂閱隊(duì)列與命名隊(duì)列或回復(fù)隊(duì)列之間的關(guān)鍵區(qū)別是訂閱隊(duì)列名稱與路由目的無(wú)關(guān),路由是通過(guò)抽象匹配條件來(lái)完成的,而不是1對(duì)1路由鍵字段匹配來(lái)完成的.
    我們以常見(jiàn)的主題樹(shù)pub-sub模型進(jìn)行講解并對(duì)其實(shí)現(xiàn). 我們需要一個(gè)能夠在主題樹(shù)上匹配的交換器類型. 在AMQP中,這是"topic" 交換器類型. topic交換器會(huì)匹配類似"STOCK.USD.*"通配符, 如像"STOCK.USD.NYSE"這樣的路由鍵.
    我們不能使用默認(rèn)的交換器或綁定,因?yàn)樗鼈儾粫?huì)做topic風(fēng)格的路由. 因此我們必明確地創(chuàng)建一個(gè)綁定.以下是創(chuàng)建和綁定pub-sub訂閱隊(duì)列的偽代碼:
    Queue.Declare
    queue=<empty>
    exclusive=TRUE
    S:Queue.Declare-Ok
    queue=tmp.2
    Queue.Bind
    queue=tmp.2
    TO exchange=amq.topic
    WHERE routing-key=STOCK.USD.*
    要從訂閱隊(duì)列中消費(fèi)消息,消費(fèi)者需要這樣做:
    Basic.Consume
    queue=tmp.2
    當(dāng)發(fā)布消息時(shí),生產(chǎn)者可以這樣做:
    Basic.Publish
    exchange=amq.topic
    routing-key=STOCK.USD.ACME
    topic交換器會(huì)使用其它綁定表處理傳入的路由鍵("STOCK.USD.ACME"),并會(huì)找到一個(gè)匹配項(xiàng)tmp.2.然后它會(huì)把消息路由到那個(gè)訂閱隊(duì)列上.
    2.2 AMQP 命令架構(gòu)
    本章節(jié)解釋了應(yīng)用程序如何與服務(wù)器對(duì)話.
    2.2.1 協(xié)議命令 (類&方法)
    中間件是復(fù)雜的,我們?cè)谠O(shè)計(jì)協(xié)議結(jié)構(gòu)的挑戰(zhàn)是要馴服其復(fù)雜性。
    我們的方法是基于類來(lái)建立傳統(tǒng)API模型,這個(gè)類中包含方法,并定義了方法明確應(yīng)該做什么.
    這會(huì)導(dǎo)致大量的命令集合,但一個(gè)命令應(yīng)該相對(duì)容易理解.
    AMQP命令組合在類中.每個(gè)類都覆蓋了一個(gè)特定功能領(lǐng)域.有此類是可選的 -每個(gè)節(jié)點(diǎn)都實(shí)現(xiàn)了需要支持的類.
    有兩種不同方法對(duì)話:
     同步請(qǐng)求-響應(yīng),在其中一個(gè)節(jié)點(diǎn)發(fā)送請(qǐng)求,另一個(gè)節(jié)點(diǎn)發(fā)送回復(fù).
    同步請(qǐng)求和響應(yīng)適用于性能不是關(guān)鍵的地方.
     異步通知, 在其中,一個(gè)節(jié)點(diǎn)發(fā)送消息但不希望得到回復(fù).異步方法適用于性能是至關(guān)重要的地方.
    為使處理方法簡(jiǎn)單,我們?yōu)槊總€(gè)異步請(qǐng)求定義了不同的回復(fù). 也就是說(shuō),沒(méi)有哪個(gè)方法可作為兩個(gè)不同請(qǐng)求的回復(fù).這意味著一個(gè)節(jié)點(diǎn),發(fā)送一個(gè)同步請(qǐng)求后,可以接受和處理傳入的方法,直到得到一個(gè)有效的同步答復(fù). 這使得AMQP與更加傳統(tǒng)的RPC協(xié)議是有區(qū)別的.
    方法可以形式上定義為同步請(qǐng)求,同步回復(fù)(針對(duì)特定請(qǐng)求),或者是異步的. 最后,每個(gè)方法都形貌地定義為客戶端(即. 服務(wù)器到客戶端),或服務(wù)端(客戶端到服務(wù)器).
    2.2.2 映射AMQP到中間件API
    我們已經(jīng)設(shè)計(jì)AMQP是可映射到中間件的API.這種映射有一些是智能的(不是所有方法, 也不是所有參數(shù)對(duì)應(yīng)用程序來(lái)說(shuō)都是有意義的),也有一些是機(jī)械的(給定一些規(guī)則,所有方法都可以在無(wú)人工干預(yù)的情況下映射).
    這么做的優(yōu)勢(shì)是對(duì)于那些了解AMQP語(yǔ)義(本章描述的類)的開(kāi)發(fā)者會(huì)在它們使用的環(huán)境中找到相同的語(yǔ)義.
    例如,下面是Queue.Declare 方法示例:
    Queue.Declare
    queue=my.queue
    auto-delete=TRUE
    exclusive=FALSE
    這會(huì)轉(zhuǎn)換為線路級(jí)幀(wire-level frame):

    或者更高級(jí)的API:
    映射為異步方法的偽代碼邏輯是:



    映射為同步方法的偽代碼邏輯是:



    值得一提的是,對(duì)于大部分應(yīng)用程序, 中間件可以完全隱藏在技術(shù)層面中, 而且實(shí)際API使用的影響會(huì)小于中間件的健壯性和能力性.
    2.2.3 無(wú)確認(rèn)
    一個(gè)聊天式協(xié)議(chatty protocol)是很慢的. 如果在這些情況中,性能是很嚴(yán)重的,我們會(huì)使用異步.
    一般我們從一個(gè)節(jié)點(diǎn)發(fā)送消息到另一個(gè)節(jié)點(diǎn). 我們會(huì)使發(fā)送方法盡可能地快,而不用等待確認(rèn).在必要時(shí),我們可以以較高級(jí)別來(lái)實(shí)現(xiàn)窗口和限制,如以消費(fèi)者水平.
    我們免除了確認(rèn),因?yàn)槲覀優(yōu)樗胁僮魇褂昧藬嘌阅P? 要么它們成功,要么就是我們有關(guān)閉通道或連接的異常.
    AMQP中可以沒(méi)有確認(rèn).成功是寂靜的,而失敗是喧鬧的.當(dāng)應(yīng)用程序明確需要追蹤成功和失敗時(shí),它們應(yīng)該使用事務(wù).
    2.2.4 Connection類
    AMQP是一個(gè)連接協(xié)議. 連接設(shè)計(jì)為長(zhǎng)期的,且可運(yùn)載多個(gè)通道. 連接生命周期是這樣的:
     client打開(kāi)與服務(wù)器的TCP/IP連接并發(fā)送一個(gè)協(xié)議頭(protocol header).這只是client發(fā)送的數(shù)據(jù),而不是作為方法格式的數(shù)據(jù).
     server使用其協(xié)議版本和其它屬性,包括它支持安全機(jī)制列表(Start方法)進(jìn)行響應(yīng).
     client選擇一種安全機(jī)制(Start-Ok).
     server開(kāi)始認(rèn)證過(guò)程, 它使用SASL的質(zhì)詢-響應(yīng)模型(challenge-response model). 它向客戶端發(fā)送一個(gè)質(zhì)詢(Secure).
     client向server發(fā)送一個(gè)認(rèn)證響應(yīng)(Secure-Ok). 例如,對(duì)于使用"plain"機(jī)制,響應(yīng)會(huì)包含登錄用戶名和密碼.
    server 重復(fù)質(zhì)詢(Secure) 或轉(zhuǎn)到協(xié)商,發(fā)送一系列參數(shù),如最大幀大小(Tune).
     client接受或降低這些參數(shù)(Tune-Ok).
     client 正式打開(kāi)連接并選擇一個(gè)虛擬主機(jī)(Open).
     服務(wù)器確認(rèn)虛擬主機(jī)是一個(gè)有效的選擇 (Open-Ok).
     客戶端現(xiàn)在使用希望的連接.
     一個(gè)節(jié)點(diǎn)(client 或 server) 結(jié)束連接(Close).
     另一個(gè)節(jié)點(diǎn)對(duì)連接結(jié)束握手(Close-Ok).
     server 和 client關(guān)閉它們的套接字連接.
    沒(méi)有為不完全打開(kāi)的連接上的錯(cuò)誤進(jìn)行握手. 根據(jù)成功協(xié)議頭協(xié)商(后面有詳細(xì)定義),在發(fā)送或收到Open 或Open-Ok之前,如果一個(gè)節(jié)點(diǎn)檢測(cè)到錯(cuò)誤,這個(gè)節(jié)點(diǎn)必須關(guān)閉socket,而不需要發(fā)送任何進(jìn)一步的數(shù)據(jù)。
    2.2.5 Channel 類
    AMQP是一個(gè)多通道協(xié)議. 通道提供了一種方式來(lái)將一個(gè)重量級(jí)TCP/IP連接分成多個(gè)輕量級(jí)連接.
    這使得協(xié)議對(duì)于防火墻更加友好,因?yàn)槎丝谑褂檬强深A(yù)測(cè)的. 這也意味著傳輸調(diào)整和網(wǎng)絡(luò)服務(wù)質(zhì)量可以得到更好的利用.
    通道是獨(dú)立的,它們可以同時(shí)執(zhí)行不同的功能,可用帶寬會(huì)在當(dāng)前活動(dòng)之間共享.
    這是令人期待的,我們鼓勵(lì)多線程客戶端應(yīng)用程序經(jīng)常使用"每個(gè)通道一個(gè)線程"編程模型.
    然而,從單個(gè)client打開(kāi)一個(gè)或多個(gè)AMQP servers連接也是完全可以接受的.
    通道生命周期如下:
    1. client打開(kāi)一個(gè)新通道(Open).
    2. server確認(rèn)新通道準(zhǔn)備就緒(Open-Ok).
    3. client和server按預(yù)期來(lái)使用通道.
    4. 一個(gè)節(jié)點(diǎn)(client或server) 關(guān)閉了通道(Close).
    5. 另一個(gè)節(jié)點(diǎn)對(duì)通道關(guān)閉進(jìn)行握手(Close-Ok).
    2.2.6 Exchange 類
    交換器類讓應(yīng)用程序來(lái)管理服務(wù)器上的交換器。這個(gè)類可以讓應(yīng)用程序腳本自己布線(而不是依賴于一些配置接口)。注:大多數(shù)應(yīng)用程序不需要這個(gè)級(jí)別的復(fù)雜度,傳統(tǒng)的中間件是不太可能能夠支持這種語(yǔ)義。
    交換器生命周期如下:
    1. client 請(qǐng)求server確保交換器是否存在(Declare). client可細(xì)化到,"如果交換器不存在則進(jìn)行創(chuàng)建",或 "如果交換器不存在,警告我,不需要?jiǎng)?chuàng)建".
    2. client發(fā)布消息到交換器.
    3. client可選擇刪除交換器(Delete).
    2.2.7 Queue 類
    queue類可讓應(yīng)用程序來(lái)管理服務(wù)器上的消息隊(duì)列. 在幾乎所有消費(fèi)消息的應(yīng)用程序中,這是基本步驟,至少要驗(yàn)證期望的消息隊(duì)列是否實(shí)際存在.
    持久化消息隊(duì)列的生命周期相當(dāng)簡(jiǎn)單:
    1. client斷言消息隊(duì)列存在(Declare, 使用"passive"參數(shù)).
    2. server確認(rèn)消息隊(duì)列存在(Declare-Ok).
    3. client從消息隊(duì)列中讀取消息。
    臨時(shí)消息隊(duì)列的生命周期更加有趣:
    1. client創(chuàng)建消息隊(duì)列(Declare,不提供隊(duì)列名稱,服務(wù)器會(huì)分配一個(gè)名稱). server 確認(rèn)(Declare-Ok).
    2. client 在消息隊(duì)列上啟動(dòng)一個(gè)消費(fèi)者. 消費(fèi)者的精確功能是由Basic類定義的。
    3. client 取消消費(fèi)者, 要么是顯示取消,要么是通過(guò)關(guān)閉通道/連接隱式取消的
    4. 當(dāng)最后一個(gè)消費(fèi)者從消息隊(duì)列中消失的時(shí)候,在過(guò)了禮貌性超時(shí)后,server會(huì)刪除消息隊(duì)列.
    AMQP 像消息隊(duì)列一樣為主題訂閱實(shí)現(xiàn)了分發(fā)機(jī)制. 這使結(jié)構(gòu)更多有趣,訂閱可以在合作訂閱應(yīng)用程序池中進(jìn)行負(fù)載均衡.
    訂閱生命周期涉及到額外的綁定階段:
    1. client 創(chuàng)建消息隊(duì)列(Declare),server進(jìn)行確認(rèn)(Declare-Ok).
    2. client 綁定消息隊(duì)列到一個(gè)topic交換器 (Bind),server進(jìn)行確認(rèn)(Bind-Ok).
    3. client像前面的例子來(lái)使用消息隊(duì)列.
    2.2.8 Basic 類
    Basic 類實(shí)現(xiàn)本規(guī)范中描述的消息功能.它支持如下主要語(yǔ)義:
     從client發(fā)送消息給server, 異步發(fā)生(Publish)
     啟動(dòng)和停止消費(fèi)者(Consume, Cancel)
     從server發(fā)送消息給client, 異步發(fā)生(Deliver, Return)
     應(yīng)答消息(Ack, Reject)
     同步從消息隊(duì)列中取消息 (Get).
    2.2.9 Transaction 類
    AMQP 支持兩種類型的事務(wù):
    1. 自動(dòng)事務(wù): 每個(gè)發(fā)布的消息和應(yīng)答都處理為獨(dú)立事務(wù).
    2. Server 本地事務(wù), 服務(wù)器會(huì)緩存發(fā)布的消息和應(yīng)答,并會(huì)根據(jù)需要由client來(lái)提交它們.
    Transaction 類(“tx”) 使應(yīng)用程序可訪問(wèn)第二種類型,即服務(wù)器事務(wù)。這個(gè)類的語(yǔ)義是:
    1. 應(yīng)用程序要求在每個(gè)通道中都有事務(wù)(Select).
    2. 應(yīng)用程序做一些工作(Publish, Ack).
    3. 應(yīng)用程序提交或回滾工作(Commit, Roll-back).
    4. 應(yīng)用程序做一些工作,循環(huán)往復(fù)。
    事務(wù)能覆蓋發(fā)布內(nèi)容和應(yīng)答,但不能覆蓋投遞(deliveries). 因此回滾不能導(dǎo)致消息重新入隊(duì)或者重新投遞, 客戶端有權(quán)在事務(wù)中確認(rèn)這些消息。
    2.3 AMQP 傳輸架構(gòu)
    這個(gè)章節(jié)解釋了命令是如何映射到線路協(xié)議的.
    2.3.1 一般描述
    AMQP是二進(jìn)制協(xié)議. 信息被組織成各種類型的幀(frames). Frames可以攜帶協(xié)議方法和其它信息.所有 幀(frames)都有同樣的格式: 幀頭(frame header),幀負(fù)載(frame payload)和幀尾(frame end).幀負(fù)載( frame payload)的格式依賴于幀類型(frame type).
    我們假設(shè)有一個(gè)可靠的面向流的網(wǎng)絡(luò)傳輸層(TCP/IP或相當(dāng)?shù)?.
    在單個(gè)套接字連接中,可以存在多個(gè)獨(dú)立控制線程,它們被稱為通道.
    每個(gè)幀都使用通道編號(hào)來(lái)編號(hào).通過(guò)交織它們的幀,不同的通道共享連接。對(duì)于任何給定的通道,幀運(yùn)行在一個(gè)嚴(yán)格的序列,這樣可以用來(lái)驅(qū)動(dòng)一個(gè)協(xié)議解析器(通常是一個(gè)狀態(tài)機(jī)).
    我們使用一組小的數(shù)據(jù)類型,如位,整數(shù),字符串和字段表來(lái)構(gòu)造幀。幀字段是緊密包裝的,不會(huì)使得它們緩慢或解析復(fù)雜。從協(xié)議規(guī)范中生成框架層是相對(duì)簡(jiǎn)單的。
    線路級(jí)格式的設(shè)計(jì)是可擴(kuò)展性,一般可以用于任意的高層協(xié)議(不只是AMQP)。我們假設(shè)AMQP將來(lái)會(huì)擴(kuò)展、改進(jìn),隨時(shí)間的推移線路級(jí)格式仍然會(huì)得到支持。
    2.3.2 數(shù)據(jù)類型
    AMQP數(shù)據(jù)類型用于方法幀中,它們是:
     Integers ( 1到8?jìng)€(gè)字節(jié)),用來(lái)表示大小,數(shù)量,范圍等等. Integers通常是無(wú)符號(hào)的,在幀中可能是未對(duì)齊的.
     Bits,用來(lái)表示開(kāi)/關(guān)值.位被包裝成字節(jié)。
     短字符串(short string),用來(lái)保存短的文本屬性.短字符串限制為255個(gè)字節(jié),可以在無(wú)緩沖區(qū)溢出的情況下進(jìn)行解析.
     長(zhǎng)字符串(long string),用來(lái)保存二進(jìn)制數(shù)據(jù)塊.
     字段表(Field tables),用來(lái)保存名稱-值對(duì)(name-value pairs). 字段值類型可以是字符串,整數(shù)等等.
    2.3.3 協(xié)議協(xié)商
    AMQP client 和server 可對(duì)協(xié)議進(jìn)行協(xié)商.這就是說(shuō)當(dāng)client連接時(shí),server可處理client能接受或修改的操作.當(dāng)兩個(gè)點(diǎn)對(duì)結(jié)果達(dá)成一致時(shí), 連接會(huì)繼續(xù)前行.協(xié)商是一種有用的技術(shù),因?yàn)樗屛覀兛梢詳嘌约僭O(shè)和前提條件。在AMQP,我們協(xié)商協(xié)議的下面方面:
     實(shí)現(xiàn)協(xié)議和版本. server 可在同一個(gè)端口上保存多個(gè)協(xié)議.
     加密參數(shù)和兩者之間的認(rèn)證.這是功能層的一部分,以前解釋過(guò)。
     最大幀大小,通道數(shù)量,以及其它操作限制.
    達(dá)成一致的限制可能會(huì)使兩者重新分配關(guān)鍵緩存區(qū)以避免死鎖.每個(gè)傳入的幀要么服從達(dá)成的限制(這是安全的),或者超過(guò)它們(在這種情況下,另一方必須斷開(kāi)連接).這非常符合"它要么工作,要么就完全不工作"的AMQP哲學(xué).
    兩個(gè)節(jié)點(diǎn)達(dá)成一致的最低限度為:
     服務(wù)器必須告訴客戶端它提出了什么限制。
     客戶端進(jìn)行響應(yīng),并可能減少其連接的限制。
    2.3.4 限制幀
    TCP/IP是一個(gè)流協(xié)議,即沒(méi)有限制幀的內(nèi)建機(jī)制. 現(xiàn)有協(xié)議可以幾種不同的方式解決這個(gè)問(wèn)題:
     每個(gè)連接中只發(fā)送單個(gè)幀.這很簡(jiǎn)單,但很慢.
     在流中添加幀定界符.這很簡(jiǎn)單,但解析較慢.
     計(jì)算幀的大小, 并在每個(gè)幀的前面發(fā)送大小。這是簡(jiǎn)單和快速,和我們的選擇.
    2.3.5 幀細(xì)節(jié)
    所有的幀都由一個(gè)頭(header,7個(gè)字節(jié)),任意大小的負(fù)載(payload),和一個(gè)檢測(cè)錯(cuò)誤的幀結(jié)束(frame-end)字節(jié)組成:

    要讀取一個(gè)幀,我們必須:
    1. 讀取header,檢查幀類型(frame type)和通道(channel).
    2. 根據(jù)幀類型,我們讀取負(fù)載并進(jìn)行處理.
    3. 讀取幀結(jié)束字節(jié).
    在實(shí)際實(shí)現(xiàn)中,如果性能很關(guān)鍵的話,我們應(yīng)該使用讀前緩沖(read-ahead buffering)”或“收集讀取(gathering reads)”,以避免為了讀一個(gè)幀而做三次獨(dú)立的系統(tǒng)調(diào)用。
    2.3.5.1 方法幀
    方法幀可以攜帶高級(jí)協(xié)議命令(我們稱之為方法(methods)).一個(gè)方法幀攜帶一個(gè)命令. 方法幀負(fù)載有下面的格式:



    要處理一個(gè)方法幀,我們必須:
    1. 讀取方法幀負(fù)載.
    2. 將其拆包成結(jié)構(gòu). 方法通常有相同的結(jié)構(gòu),因此我們可以快速對(duì)方法進(jìn)行拆包.
    3. 檢查在當(dāng)前上下文中是否允許出現(xiàn)方法.
    4. 檢查方法參數(shù)是否有效.
    5.執(zhí)行方法.
    方法主體(bodies) 由AMQP數(shù)據(jù)字段(位,整數(shù), 字符串和字符串表組成)構(gòu)成. 編組代碼直接從協(xié)議規(guī)范中生成,因此是非常快速地.
    2.3.5.2 內(nèi)容幀
    內(nèi)容是我們通常AMQP服務(wù)器在客戶端與客戶端之間傳送和應(yīng)用數(shù)據(jù). 粗略地說(shuō),內(nèi)容是由一組屬性加上一個(gè)二進(jìn)制數(shù)據(jù)部分組成的。它所允許的屬性集合由Basic類定義,而這些屬性的形式為內(nèi)容頭幀(content header frame)。其數(shù)據(jù)可以是任何大小,也有可能被分解成幾個(gè)(或多個(gè))塊,每一個(gè)都有內(nèi)容體幀(content body frame)。
    看一個(gè)特定通道的幀,當(dāng)它們?cè)诰€路上傳輸時(shí),我們可能會(huì)看到下面這樣的東西:


    某些方法(如Basic.Publish, Basic.Deliver等等.)通常情況下定義為傳輸內(nèi)容.
    當(dāng)一個(gè)節(jié)點(diǎn)發(fā)送像這樣的方法幀時(shí),它總是會(huì)遵循一個(gè)內(nèi)容頭幀(conent header frame)和零個(gè)或多個(gè)內(nèi)容體幀(content body frame)的形式.
    一個(gè)內(nèi)容頭幀有下面的格式:
    某些方法(如Basic.Publish, Basic.Deliver等等.)通常情況下定義為傳輸內(nèi)容.
    當(dāng)一個(gè)節(jié)點(diǎn)發(fā)送像這樣的方法幀時(shí),它總是會(huì)遵循一個(gè)內(nèi)容頭幀(conent header frame)和零個(gè)或多個(gè)內(nèi)容體幀(content body frame)的形式.
    一個(gè)內(nèi)容頭幀有下面的格式:

    我們將內(nèi)容體放置在不同的幀中(并不包含在方法中),因此AMQP可支持零拷貝技術(shù),這樣其內(nèi)容就不需要編組或編碼. 我們將內(nèi)容屬性安放在它們自己的幀中,以便收件人可以有選擇地丟棄他們不想處理的內(nèi)容。
    2.3.5.3 心跳幀
    心跳是一種設(shè)計(jì)用來(lái)撤銷(undo)TCP/IP功能的技術(shù),也就是說(shuō)在長(zhǎng)時(shí)間超時(shí)后,它有能力通過(guò)關(guān)閉broker物理連接來(lái)進(jìn)行恢復(fù).在某些情景下,我們需要快速知道節(jié)點(diǎn)連接是否斷開(kāi)了,或者是由于什么原因不能響應(yīng)了.因?yàn)樾奶梢栽谳^低水平上進(jìn)行,我們?cè)趥鬏攲哟紊习垂?jié)點(diǎn)交換的特定幀類型來(lái)處理,而不是按類方法.
    2.3.6 錯(cuò)誤處理
    AMQP使用異常來(lái)處理錯(cuò)誤.任何操作錯(cuò)誤(未找到消息隊(duì)列,訪問(wèn)權(quán)限不足)都會(huì)導(dǎo)致一個(gè)通道異常. 任何結(jié)構(gòu)化的錯(cuò)誤(無(wú)效參數(shù),壞序列的方法.)都會(huì)導(dǎo)致一個(gè)連接異常.異常會(huì)關(guān)閉通道或連接,同時(shí)也會(huì)向客戶端應(yīng)用返回響應(yīng)碼和響應(yīng)文本.我們使用了類似于HTTP等協(xié)議和其它大多數(shù)協(xié)議中的三位回復(fù)代碼和文字回復(fù)文本方案.
    2.3.7 關(guān)閉通道和連接
    連接或通道,對(duì)于客戶端來(lái)說(shuō),當(dāng)其發(fā)送Open時(shí)則被認(rèn)為是“打開(kāi)”的,對(duì)于服務(wù)器端來(lái)說(shuō),當(dāng)其發(fā)送Open-Ok時(shí)則被認(rèn)為是打開(kāi)的。基于這一點(diǎn),一個(gè)希望關(guān)閉通道或連接的對(duì)等體也必須使用握手協(xié)議來(lái)這樣做。
    可出于任何原因,可能會(huì)正常地或異常地關(guān)閉一個(gè)通道或連接-因此必須仔細(xì)小心。
    對(duì)于突然或意外關(guān)閉,并不能得到快速探測(cè),因此當(dāng)發(fā)生異常時(shí),我們可能會(huì)丟失錯(cuò)誤回復(fù)代碼。
    正確的設(shè)計(jì)是對(duì)于所有關(guān)閉必須進(jìn)行握手,使我們關(guān)閉后對(duì)方知道相應(yīng)的情況。
    當(dāng)一個(gè)節(jié)點(diǎn)決定關(guān)閉一個(gè)通道或連接時(shí),它發(fā)送一個(gè)Close方法。接收節(jié)點(diǎn)必須使用Close-Ok來(lái)響應(yīng)Close,然后雙方可以關(guān)閉他們的通道或連接。請(qǐng)注意,如果節(jié)點(diǎn)忽略了關(guān)閉,當(dāng)兩個(gè)節(jié)點(diǎn)同時(shí)發(fā)送Close時(shí),可能會(huì)發(fā)生死鎖。
    2.4 AMQP Client 架構(gòu)
    可直接從應(yīng)用程序中讀寫AMQP幀,但這是相當(dāng)糟糕的設(shè)計(jì).
    即使是最簡(jiǎn)單的對(duì)話框也比較復(fù)雜(比如同HTTP比較),應(yīng)用程序開(kāi)發(fā)者沒(méi)必要為了向消息隊(duì)列發(fā)送消息, 而來(lái)理解二進(jìn)制這樣的東西. 推薦的AMQP client架構(gòu)須由下面的多個(gè)抽象層組成:
    1. 幀層. 此層接受AMQP協(xié)議方法,并按某種語(yǔ)言格式(結(jié)構(gòu),類等等) 來(lái)序列化成線路級(jí)幀.幀層可以根據(jù)AMQP規(guī)范機(jī)械產(chǎn)生(這是在一個(gè)協(xié)議的建模語(yǔ)言,專為AMQP定義了XML實(shí)現(xiàn)).
    2. 連接管理層. 此層用于讀寫AMQP幀,并管理所有連接,會(huì)話邏輯.在此層中,我們可以封裝打開(kāi)連接和會(huì)話,錯(cuò)誤處理,內(nèi)容傳輸和接收的全部邏輯. 此層的大部分都可通過(guò)AMQP規(guī)范來(lái)生成.例如,規(guī)范定義了哪些方法可以攜帶內(nèi)容, 因?yàn)檫壿嫲l(fā)送方法和可選的發(fā)送內(nèi)容可以機(jī)械的生成.
    3. API 層. 此層暴露了應(yīng)用程序工作的特定API. API層可能會(huì)反映一些現(xiàn)有的標(biāo)準(zhǔn),或暴露高層AMQP的方法,或?qū)Ρ竟?jié)前面介紹的內(nèi)容做一個(gè)映射。AMQP方法設(shè)計(jì)為使這些映射簡(jiǎn)單有用。API層本身可能是由多個(gè)層組成的,如.構(gòu)建于AMQP方法API之上的高級(jí)API.
    此外,通常還會(huì)有一些I / O層,這此可以是非常簡(jiǎn)單的(同步套接字讀取和寫入)或復(fù)雜的(完全異步多線程I / O)。此圖顯示了整體推薦的架構(gòu):

    在本文檔中,當(dāng)我們說(shuō)"client API"的時(shí)候,我們指的則是應(yīng)用程序下的所有層(i/o,幀,連接按理和API層).我們通常將客戶端API和應(yīng)用程序分開(kāi)說(shuō), 在這里,應(yīng)用程序會(huì)使用客戶端API來(lái)同中間件服務(wù)器進(jìn)行對(duì)話.
    3 功能說(shuō)明
    3.1 Server 功能說(shuō)明
    3.1.1 消息和內(nèi)容
    消息是中間件路由和隊(duì)列系統(tǒng)處理的原子單元。消息可攜帶一份內(nèi)容,它包括一個(gè)內(nèi)容頭,一組屬性,和一個(gè)內(nèi)容體,和持有一個(gè)不透明的二進(jìn)制數(shù)據(jù)塊。
    一個(gè)消息可以對(duì)應(yīng)到許多不同應(yīng)用程序的實(shí)體:
     一個(gè)應(yīng)用程序級(jí)消息
     一個(gè)傳輸文件
     一個(gè)數(shù)據(jù)流幀等等.
    消息可以持久化.一個(gè)持久化消息可以安全地存儲(chǔ)在磁盤上,即使是在嚴(yán)重的網(wǎng)絡(luò)故障,服務(wù)器崩潰、溢出等情況下也可確保投遞.消息也可以有優(yōu)先級(jí).高優(yōu)先級(jí)消息會(huì)在等待同一個(gè)消息隊(duì)列時(shí),在低優(yōu)先級(jí)消息之前發(fā)送. 當(dāng)消息必須被丟棄以確保服務(wù)器質(zhì)量水平,將會(huì)優(yōu)先丟棄低優(yōu)先級(jí)消息.
    服務(wù)器不能修改接收到并將傳遞給消費(fèi)者應(yīng)用程序的消息內(nèi)容體. 服務(wù)器可在內(nèi)容頭中添加額外信息,但不能刪除或修改現(xiàn)有信息.
    3.1.2 虛擬主機(jī)(Virtual Hosts)
    虛擬主機(jī)是服務(wù)器內(nèi)的數(shù)據(jù)分區(qū), 它為在共享基礎(chǔ)設(shè)施上的管理帶來(lái)了方便.
    一個(gè)虛擬主機(jī)包括其命名空間,一組交換器,消息隊(duì)列以及所有相關(guān)對(duì)象. 每個(gè)連接必須關(guān)聯(lián)一個(gè)單個(gè)虛擬主機(jī).
    在認(rèn)證后,客戶端可在Connection.Open方法中選擇虛擬主機(jī). 這意味著,服務(wù)器上的認(rèn)證方案可在此服務(wù)器上的所有虛擬主機(jī)上共享. 然而,對(duì)于每個(gè)虛擬主機(jī)來(lái)說(shuō),也可以獨(dú)特的認(rèn)證方案. 對(duì)于每個(gè)虛擬主機(jī)需要不同的身份驗(yàn)證方案的管理員應(yīng)該使用單獨(dú)的服務(wù)器。
    連接中的所有通道都在同一個(gè)虛擬主機(jī)上工作.在同一個(gè)連接中,沒(méi)有與不同虛擬主機(jī)通信的方式, 也沒(méi)有在不斷開(kāi)連接重新開(kāi)始的情況下,切換到其它虛擬主機(jī)的可能性.
    該協(xié)議沒(méi)有提供用于創(chuàng)建或配置虛擬主機(jī)的機(jī)制-這在服務(wù)器內(nèi)是一個(gè)不確定的方式,是完全依賴于實(shí)現(xiàn)的。
    3.1.3 交換器
    交換器是一個(gè)虛擬主機(jī)內(nèi)的消息路由代理。交換器實(shí)例(我們通常稱之為“交換器”)接受消息和路由信息-主要是一個(gè)路由鍵-或者將消息傳遞到消息隊(duì)列,或到內(nèi)部服務(wù)。交換器是基于每個(gè)虛擬主機(jī)命名的。
    應(yīng)用程序可以在權(quán)限范圍內(nèi)自由地創(chuàng)建、共享、使用和銷毀交換器實(shí)例.交換器可能是持久的、臨時(shí)的或自動(dòng)刪除的。持久化的交換器會(huì)持續(xù)到他們被刪除,臨時(shí)的交換器會(huì)持續(xù)到服務(wù)器關(guān)閉。自動(dòng)刪除的交換器直到他們不再使用。服務(wù)器提供了一組特定的交換器類型。每個(gè)交換器類型都實(shí)現(xiàn)了一個(gè)特定的匹配和算法,如下一節(jié)中定義的。AMQP只要求少量的交換器類型,并推薦了一些。此外,每個(gè)服務(wù)器實(shí)現(xiàn)可以添加自己的交換類型。
    交換器可以將單個(gè)消息并發(fā)地路由到的消息隊(duì)列中。這將創(chuàng)建一個(gè)獨(dú)立消息的多個(gè)實(shí)例。
    3.1.3.1 Direct交換器類型
    direct 交換器按如下方式來(lái)工作:
    1. 消息隊(duì)列使用路由鍵K來(lái)綁定交換器.
    2. 發(fā)布者使用路由鍵R來(lái)向交換器發(fā)送消息.
    3. 在K=R時(shí),消息會(huì)傳遞到消息隊(duì)列中.
    server必須實(shí)現(xiàn)direct交換器,并且在每個(gè)虛擬主機(jī)中必須預(yù)定義兩個(gè)direct交換器: 一個(gè)名為 amq.direct, 另一個(gè)無(wú)公共名稱(為Publish方法的默認(rèn)交換器).
    注意,消息隊(duì)列可以使用任何有效的路由鍵值進(jìn)行綁定,但通常消息隊(duì)列使用它們自己的名稱作路由鍵來(lái)綁定.
    事實(shí)上,所有消息隊(duì)列必須能使用其自身隊(duì)列名稱作路由鍵自動(dòng)綁定無(wú)名稱的交換器上.
    3.1.3.2 Fanout 交換器類型
    fanout交換器類型按如下方式來(lái)工作:
    1. 消息隊(duì)列不使用參數(shù)來(lái)綁定交換器.
    2. 發(fā)布者向交換器發(fā)送消息.
    3. 消息無(wú)條件傳遞給消息隊(duì)列。
    fanout 交換器是微不足道的設(shè)計(jì)與實(shí)現(xiàn).此交換器類型和預(yù)聲明的交換器稱為amq.fanout,它是強(qiáng)制的.
    3.1.3.3 Topic交換器類型
    topic交換器類型按如下方式來(lái)工作:
    1. 消息隊(duì)列使用路由模式P來(lái)綁定到交換器.
    2. 發(fā)布者使用路由鍵R來(lái)向交換器發(fā)送消息.
    3. 當(dāng)R匹配P時(shí),消息將被傳遞到消息隊(duì)列.
    用于topic交換器的路由鍵必須由0個(gè)或多個(gè)由點(diǎn)號(hào)
    用于topic交換器的路由鍵必須由點(diǎn)分隔的零或多個(gè)單詞組成.每個(gè)單詞必須包含字母A-Z和a-z 以及數(shù)字0-9.
    路由模式與路由鍵遵循相同的規(guī)則,* 用于匹配單個(gè)單詞,# 用于匹配0個(gè)或多個(gè)單詞.因此路由模式*.stock.# 會(huì)匹配路由鍵usd.stock 和eur.stock.db 但不匹配stock.nasdaq.
    對(duì)于topic交換器我們建議的設(shè)計(jì)是保持所有已知路由鍵的集合,當(dāng)發(fā)布者使用了新的路由鍵時(shí),才更新此集合. 通過(guò)給定一個(gè)路由鍵來(lái)確實(shí)所有綁定是可能的,因此可為消息快速找到消息隊(duì)列. 此交換器類型是可選的.
    server應(yīng)該實(shí)現(xiàn)topic交換器類型,在這種情況下,server 必須在每個(gè)虛擬主機(jī)中預(yù)先定義至少一個(gè) topic交換器,其名稱為amq.topic.
    3.1.3.4 Headers交換器類型
    headers交換器類型按如下方式進(jìn)行工作:
    1. 消息隊(duì)列使用包含匹配綁定和帶有默認(rèn)值的header參數(shù)表來(lái)綁定交換器.在這種交換器類型中,不使用路由鍵.
    2.發(fā)布者向交換器發(fā)送消息,這些消息的headers屬性中包含名稱-值對(duì)的表.
    3.如果消息頭屬性與隊(duì)列綁定的參數(shù)相匹配,則消息傳遞給隊(duì)列。
    匹配算法是由參數(shù)表中的名稱值對(duì)這樣的特殊綁定參數(shù)來(lái)控制的. 這個(gè)參數(shù)的名稱是'x-match'.
    它可以接受兩種值, 以表示表格中其它的名稱值對(duì)將如何來(lái)進(jìn)行匹配:
     'all' 則表明所有其它的名稱值對(duì)必須與路由消息的頭屬性相匹配(即.AND匹配)
     'any' 則表明只要消息頭屬性中的任何一個(gè)字段匹配參數(shù)表中的字段,則消息就應(yīng)該被路由(即. OR匹配).
    綁定參數(shù)中的字段必須與消息字段中的字段相匹配,這些情況包括:如果綁定參數(shù)中的字段沒(méi)有值且在消息頭中存在相同名稱的字段,或者綁定參數(shù)中的字段有值,且消息屬性中存在同樣的字段且有相同的值。
    任何以'x-'而不是'x-match'開(kāi)頭的字段為將來(lái)保留使用并會(huì)被忽略.
    server應(yīng)該實(shí)現(xiàn)headers交換器類型, 且server必須在每個(gè)虛擬主機(jī)中預(yù)先聲明至少一個(gè)headers交換器,且名稱為amq.match.
    3.1.3.5 System交換器類型
    system交換器類型按如下方式進(jìn)行工作:
    1. 發(fā)布者使用路由鍵S來(lái)向交換器發(fā)送消息.
    2. system交換器將其傳遞給系統(tǒng)服務(wù)S.
    系統(tǒng)服務(wù)以"amq."開(kāi)頭,為AMQP保留使用. 在服務(wù)器環(huán)境中,所有其它名稱可自由使用. 此交換器類型是可選的.
    3.1.3.6 實(shí)現(xiàn)定義的交換器類型
    所有非規(guī)范交換器類型必須以"x-"開(kāi)頭. 不以"x-"開(kāi)頭的交換器作為將來(lái)AMQP標(biāo)準(zhǔn)保留使用.
    3.1.4 消息隊(duì)列
    消息隊(duì)列是一個(gè)名為FIFO的緩沖區(qū)且為一組消費(fèi)者應(yīng)用程序保存消息.
    在其權(quán)限范圍內(nèi),應(yīng)用程序可以自由地創(chuàng)建、共享、使用和銷毀消息隊(duì)列.
    注意,在一個(gè)隊(duì)列中可能存在多個(gè)讀者,或存在客戶端事務(wù),或存在使用了優(yōu)先級(jí)字段,或存在使用了消息選擇器,或特定實(shí)現(xiàn)了投遞優(yōu)化的隊(duì)列可能不會(huì)真正地展現(xiàn)出FIFO特性. 唯一可以確保FIFO的方式是只有一個(gè)消費(fèi)者連上了隊(duì)列.在那些情況下,隊(duì)列可描述為弱-FIFO.
    消息隊(duì)列可能是持久化的或自動(dòng)刪除的.持久化消息隊(duì)列會(huì)持續(xù)到它們刪除時(shí)為止. 臨時(shí)消息隊(duì)列可持續(xù)到服務(wù)器關(guān)閉時(shí)為止.自動(dòng)刪除消息隊(duì)列可持續(xù)到它們不再使用時(shí)為止.
    Message隊(duì)列可將消息存儲(chǔ)在內(nèi)存,磁盤,或兩者的組合中.消息隊(duì)列是基于虛擬主機(jī)來(lái)命名的.
    消息隊(duì)列保存信息,并可在一個(gè)或多個(gè)消費(fèi)客戶端之間進(jìn)行分發(fā).路由到消息隊(duì)列中的消息不能再發(fā)給多個(gè)客戶端,除非在失敗或拒絕后進(jìn)行重發(fā).
    單個(gè)消息隊(duì)列可在同個(gè)時(shí)間可獨(dú)立地持有不同類型的內(nèi)容.也就是,如果Basic和文件內(nèi)容都發(fā)給了同一個(gè)消息隊(duì)列,這些將會(huì)作為請(qǐng)求獨(dú)立地分發(fā)給消費(fèi)應(yīng)用程序.
    3.1.5 綁定
    綁定是消息隊(duì)列和交換器之間的關(guān)系.綁定特有的路由參數(shù)將告訴交換器那些隊(duì)列應(yīng)該得到消息. 應(yīng)用程序可根據(jù)需要來(lái)驅(qū)動(dòng)消息流向它們的消息隊(duì)列. 綁定的壽命依賴于定義它們的消息隊(duì)列 - 當(dāng)消息隊(duì)列被銷毀時(shí),其綁定也會(huì)被銷毀.Queue.Bind 方法的特定語(yǔ)義將依賴于交換器類型.
    3.1.6 消費(fèi)者
    我們使用術(shù)語(yǔ)"consumer"來(lái)表示應(yīng)用程序和控制客戶端程序來(lái)接收消息隊(duì)列中的實(shí)體.當(dāng)客戶端啟動(dòng)一個(gè)消費(fèi)者,它就在服務(wù)器中創(chuàng)建了一個(gè)消費(fèi)實(shí)體 .當(dāng)客戶端退出一個(gè)消費(fèi)者時(shí),它就銷毀了一個(gè)服務(wù)器中的消費(fèi)者實(shí)體. 屬于單個(gè)客戶端通道的消費(fèi)者可異步地將消息發(fā)送到隊(duì)列中.
    3.1.7 服務(wù)質(zhì)量
    服務(wù)質(zhì)量控制了消息發(fā)送的速度. 服務(wù)質(zhì)量依賴于被分發(fā)的內(nèi)容類型.一般的服務(wù)質(zhì)量,在客戶端應(yīng)答消息前,會(huì)使用預(yù)提取的概念來(lái)指定發(fā)送多少個(gè)消息或多少個(gè)字節(jié)的數(shù)量. 目標(biāo)是提前發(fā)送消息數(shù)據(jù),以減少延遲。
    3.1.8 確認(rèn)/應(yīng)答
    應(yīng)答是從客戶端程序發(fā)出的正式信號(hào),用以表示消息隊(duì)列中的消息已經(jīng)得到成功處理. 有兩種應(yīng)答模型:
    1. 自動(dòng)地(Automatic), 在這種情況下,只要消息投遞到了應(yīng)用程序,服務(wù)器就會(huì)立即從消息隊(duì)列中刪除消息(通過(guò) Deliver 或 Get-Ok 方法).
    2. 明確地(Explicit),在這種情況下,客戶端程序必須對(duì)每個(gè)消息發(fā)磅一個(gè)Ack方法以表示消息被處理了.客戶端層可以不同方式來(lái)實(shí)現(xiàn)明確應(yīng)答,如.只要收到了消息或當(dāng)應(yīng)用程序表示消息已經(jīng)處理了.
    這些區(qū)別不會(huì)影響AMQP或互操作性.
    3.1.9 流控制(Flow Control)
    流控制是一個(gè)用來(lái)中止節(jié)點(diǎn)消息流的緊急過(guò)程. 它在客戶端和服務(wù)器端都按同樣方式工作,且都是由Channel.Flow命令實(shí)現(xiàn)的. 流控制是唯一可以阻止一個(gè)過(guò)度生產(chǎn)發(fā)布者的機(jī)制.如果它使用消息確認(rèn)(這通常意味著使用事務(wù)), 消費(fèi)者則可以使用更優(yōu)雅的預(yù)取機(jī)制窗口。
    3.1.10 命名約定
    這些約定規(guī)范了AMQP實(shí)體命名. 服務(wù)器和客戶端必須遵守這些約定:
     用戶定義的交換器類型前輟必須是"x-"
     標(biāo)準(zhǔn)交換器實(shí)例前輟是"amq."
     標(biāo)準(zhǔn)系統(tǒng)服務(wù)前輟是"amq."
     標(biāo)準(zhǔn)消息隊(duì)列前輟是"amq."
     所有其他的交換器、系統(tǒng)服務(wù)和消息隊(duì)列名稱都在應(yīng)用程序空間中。
    3.2 AMQP 命令說(shuō)明(Classes & Methods)
    3.2.1 解釋性注釋
    出于互操作原因,AMQP方法可以定義特定的最小值(如每消息隊(duì)列的消費(fèi)者數(shù)量)。這些極小值被定義在每個(gè)類的描述中。
    遵從AMQP的實(shí)現(xiàn)應(yīng)該為這些字段實(shí)現(xiàn)合理值, 最小值只用在最小能力的平臺(tái)上.
    語(yǔ)法使用這樣的標(biāo)記法:
     'S:' 指示從服務(wù)器發(fā)送到客戶端的數(shù)據(jù)或方法;
     'C:' 指示從客戶端發(fā)送到服務(wù)器的數(shù)據(jù)或方法;
     +term or +(...) 表達(dá)式表示1個(gè)或多個(gè)實(shí)例;
     *term or *(...) 表達(dá)式表示0個(gè)或多個(gè)實(shí)例.
    我們定義的方法是:
     一個(gè)同步請(qǐng)求("syn request").發(fā)送節(jié)點(diǎn)應(yīng)該等待特定的回復(fù)方法,但可以異步實(shí)現(xiàn)此方法;
    一個(gè)同步回復(fù)("syn reply for XYZ");
     一個(gè)異步請(qǐng)求或答復(fù) ("async").
    3.2.2 類和方法細(xì)節(jié)
    這部分是由生成的文件amqp-xml-spec.odt提供。
    4 技術(shù)說(shuō)明
    4.1 IANA分配的端口號(hào)
    IANA為標(biāo)準(zhǔn)AMQP的TCP和UDP分配了5672端口。UDP端口被保留用于將來(lái)的組播實(shí)現(xiàn)。
    4.2 AMQP 線程級(jí)格式
    4.2.1 正式協(xié)議語(yǔ)法
    我們?yōu)锳MQP提供了一個(gè)完整語(yǔ)法(這只是AMQP提供的參考,跳到下一節(jié),你會(huì)發(fā)現(xiàn)不同的幀類型和格式):


    我們使用了IETF RFC 2234中定義的增強(qiáng)BNF語(yǔ)法. 總體而言,
     規(guī)則的名稱僅僅是名稱本身。
     終端是由一個(gè)或多個(gè)數(shù)字字符指定的,這些字符的基本解釋為“d”或“x”。
     通過(guò)列出一系列規(guī)則名稱,一個(gè)規(guī)則可以定義一個(gè)簡(jiǎn)單的,有序的字符串的值.
     其他數(shù)值的范圍可以簡(jiǎn)潔指定,使用破折號(hào)(“-”)來(lái)表示替代值的范圍。
     在圓括號(hào)中的元素被視為單個(gè)元素,其內(nèi)容是嚴(yán)格有序的。
     由/分隔的元素是可替代值.
     元素之間的操作符 "*"表示重復(fù).完整格式為: "<a>*<b>element",這里<a>的<b>是可選的十進(jìn)制值, 表示只能出現(xiàn)大于<a>而小于<b>的元素.
     規(guī)則形式: "<n>element" 等價(jià)于<n>*<n>element.
     方括號(hào)中的元素是可選元素.
    4.2.2 協(xié)議頭
    client必須通常發(fā)送一個(gè)協(xié)議頭開(kāi)始新連接.它是8字節(jié)序列:

    協(xié)議頭由大寫字母"AMQP",其后跟常量%d0組成:
    1. 協(xié)議主版本號(hào), 按照章節(jié)1.4.2中描述的使用.
    2. 協(xié)議次版本號(hào), 按照章節(jié)1.4.2中描述的使用.
    3. 協(xié)議修訂版本, 按照章節(jié)1.4.2中描述的使用.
    該協(xié)議協(xié)商模型與現(xiàn)有HTTP協(xié)議兼容,使用常量文本字符串來(lái)發(fā)起連接, 并使用防火墻來(lái)檢測(cè)協(xié)議的開(kāi)始以決定應(yīng)用什么規(guī)則.
    client和服務(wù)通過(guò)以下方式來(lái)達(dá)成協(xié)議版本一致:
     client打開(kāi)一個(gè)到AMQP服務(wù)器的新socket連接,并發(fā)送協(xié)議頭.
     server可接受或拒絕協(xié)議頭.如果它拒絕了協(xié)議頭,它將會(huì)輸出一個(gè)有效的協(xié)議頭到socket,然后再關(guān)閉socket.
     否則它會(huì)同意(leaves)socket打開(kāi),并相應(yīng)地實(shí)現(xiàn)協(xié)議.
    示例:

    實(shí)現(xiàn)者指導(dǎo)方針:
     server可接受非AMQP協(xié)議,如HTTP.
     如果server無(wú)法識(shí)別socket數(shù)據(jù)中的前5個(gè)字節(jié),或者它不支持client請(qǐng)求的協(xié)議版本,它必須輸出一個(gè)有效的協(xié)議頭到socket,然后再關(guān)閉socket (必須確保client應(yīng)用程序能收到數(shù)據(jù)) ,最后再關(guān)閉socket連接.服務(wù)器可以打印診斷信息以輔助調(diào)試。
     client可使用服務(wù)器支持的最高版本來(lái)進(jìn)行檢測(cè),如果收到了服務(wù)器發(fā)回的這種信息,就可使用較低版本來(lái)進(jìn)行重連
     實(shí)現(xiàn)了多版本AMQ的Clients和servers都應(yīng)該使用8字節(jié)的協(xié)議頭來(lái)標(biāo)識(shí)協(xié)議.
    4.2.3 通用幀格式
    所有幀都以7個(gè)字節(jié)的頭開(kāi)始,其中包括一個(gè)type字段 ,一個(gè)channel字段和一個(gè)size字段:

    AMQP 定義了如下的幀類型:
     Type = 1, "METHOD": 方法幀
     Type = 2, "HEADER": 內(nèi)容頭幀
     Type = 3, "BODY": 內(nèi)容體幀.
     Type = 4, "HEARTBEAT": 心跳幀.
    通道編號(hào)為0的代表全局連接中的所有幀,1-65535代表特定通道的幀.
    size字段是負(fù)載的大小,不包括結(jié)束幀字節(jié). 由于AMQP假設(shè)是一個(gè)可靠的連接協(xié)議,我們使用結(jié)束幀來(lái)檢測(cè)錯(cuò)誤客戶端和服務(wù)器實(shí)現(xiàn)引起的錯(cuò)誤.
    實(shí)現(xiàn)者指導(dǎo)方針:
     結(jié)束幀必須是十六進(jìn)制值%xCE.
     如果一個(gè)節(jié)點(diǎn)收到了未定義類型的幀,它必須將其視為致命的協(xié)議錯(cuò)誤,并關(guān)閉連接,而不進(jìn)一步地發(fā)送任何數(shù)據(jù)
     當(dāng)一個(gè)節(jié)點(diǎn)讀取到幀時(shí),在解碼幀前,它必須檢查結(jié)束幀是否是有效的. 如果結(jié)束幀無(wú)效,它必須將其視為致使的協(xié)議錯(cuò)誤,并關(guān)閉連接,而不進(jìn)一步地發(fā)送任何數(shù)據(jù). 它應(yīng)該記錄相關(guān)問(wèn)題的日志信息,這樣就可以服務(wù)器或客戶端幀代碼實(shí)現(xiàn)中表示錯(cuò)誤.
     節(jié)點(diǎn)發(fā)送的幀大小不能超過(guò)約定的大小. 節(jié)點(diǎn)收到超過(guò)大小的幀時(shí),必須發(fā)出一個(gè)回復(fù)碼為501(幀錯(cuò)誤)的連接異常信號(hào).
     對(duì)于所有心跳幀,方法幀,連接類的頭和體,通道編號(hào)必須為0. 節(jié)點(diǎn)收到非0通道編號(hào)的這些幀必須使用回復(fù)碼503(無(wú)效命令)來(lái)發(fā)出異常信號(hào).
    4.2.4 方法負(fù)載
    方法幀的體包括一個(gè)不可變的數(shù)據(jù)字段列表,稱為"arguments".所有方法體都以類型和方法的標(biāo)識(shí)符開(kāi)始:

    實(shí)現(xiàn)者指導(dǎo)方針:
     class-id 和 method-id是由AMQP類和方法定義的常量.
     arguments 是特定于每個(gè)方法中的一組AMQP字段.
     Class id 中%x00.01-%xEF.FF范圍內(nèi)的值被AMQP標(biāo)準(zhǔn)類保留使用.
     Class id 中%xF0.00-%xFF.FF (%d61440-%d65535) 范圍內(nèi)的值可用于非標(biāo)準(zhǔn)擴(kuò)展類實(shí)現(xiàn).
    4.2.5 AMQP 數(shù)據(jù)字段
    AMQP有兩種級(jí)別的數(shù)據(jù)字段:用于方法參數(shù)的原生數(shù)據(jù)字段, 以及用于多個(gè)應(yīng)用之間傳遞數(shù)據(jù)的字段表. 字段表是原生數(shù)據(jù)字段的超集.
    4.2.5.1 Integers
    AMQP定義了這些原生整數(shù)類型:
     無(wú)符號(hào)字節(jié)(8 bits).
     無(wú)稱號(hào)短整形(16 bits).
     無(wú)符號(hào)長(zhǎng)整形(32 bits).
     無(wú)符號(hào)長(zhǎng)長(zhǎng)整形(64 bits).
    整形和字符串長(zhǎng)度總是無(wú)符號(hào)的,且按網(wǎng)絡(luò)字節(jié)順序保存. 當(dāng)存在兩個(gè)高低系統(tǒng)時(shí)(如.兩個(gè)Intel CPUS),我們不會(huì)對(duì)它們的交互嘗試優(yōu)化.
    實(shí)現(xiàn)方針:
     實(shí)現(xiàn)不能假設(shè)幀內(nèi)的整形編碼在內(nèi)存邊界中是對(duì)齊的.
    4.2.5.2 Bits
    AMQP定義了一個(gè)原生位字段類型. 位累積成整個(gè)字節(jié). 當(dāng)在幀中兩個(gè)或更多位相鄰時(shí),它們會(huì)被包裝成一個(gè)或多個(gè)字節(jié),且在每個(gè)字節(jié)中以低位開(kāi)始.
    沒(méi)有要求在一個(gè)幀中的所有位必須是連續(xù)的,但這通常是做,以盡量減少幀尺寸。
    4.2.5.3 Strings
    AMQP 字符串是可變長(zhǎng)度,由一個(gè)整數(shù)長(zhǎng)度后跟零個(gè)或多個(gè)字節(jié)數(shù)據(jù)表示. AMQP定義了兩種原生字符串類型:
     短字符串(Short strings),以8位無(wú)稱號(hào)整形長(zhǎng)度后跟0個(gè)或多個(gè)字節(jié)數(shù)據(jù)存儲(chǔ). 短字符串可攜帶最多255字節(jié)的UTF-8數(shù)據(jù), 但不能包含二進(jìn)制零字節(jié).
     長(zhǎng)字符串(Long strings), 以32位無(wú)稱號(hào)整形長(zhǎng)度后跟0個(gè)或多個(gè)字節(jié)數(shù)據(jù)存儲(chǔ). 長(zhǎng)字符串可包含任意數(shù)據(jù).
    4.2.5.4 時(shí)間戳(Timestamps)
    時(shí)間戳是以精度為1秒的64位POSIX time_t 格式保存的.使用64伴可以避免31位和32位相關(guān)的time_t值概括問(wèn)題(wraparound issues).
    4.2.5.5 字段表
    字段表是包含名稱-值對(duì)的長(zhǎng)字符串. 名稱-值對(duì)編碼為:以短字符串定義名稱,字節(jié)定義值類型和值. 有效的表字段類型是原生整形,位,字符串,時(shí)間戳類型的擴(kuò)展. 多字節(jié)整形字段通常是按網(wǎng)絡(luò)字節(jié)順序保存的.
    指導(dǎo)方針:
     字段名稱必須以字母開(kāi)頭,其后可跟'$,'#',數(shù)字,下劃線,最大長(zhǎng)度為128個(gè)字符.
     server應(yīng)該驗(yàn)證字段名稱,如果收到了無(wú)效的字段名稱,它應(yīng)該使用回復(fù)碼503(語(yǔ)法錯(cuò)誤)來(lái)發(fā)出異常信號(hào).
     十進(jìn)制值不用于支持浮點(diǎn)值,它是固定的業(yè)務(wù)值,如貨幣匯率和金額。其字節(jié)編碼代表了位置編號(hào),其后跟著一個(gè)無(wú)符號(hào)的長(zhǎng)整數(shù).“十進(jìn)制”是無(wú)符號(hào)的.
     重復(fù)字段是非法的。對(duì)于一個(gè)包含重復(fù)字段的表,其行為是未定義的。
    4.2.6 內(nèi)容幀
    某些特定的方法(Publish, Deliver, etc.) 會(huì)攜帶內(nèi)容.請(qǐng)參考 "Functional Specifications" 來(lái)了解每種方法的說(shuō)明,以及它們是否是攜帶內(nèi)容的方法.
    內(nèi)容由1個(gè)或多個(gè)幀組成:
    1. 只有一個(gè)內(nèi)容頭幀能提供內(nèi)容屬性.
    2. 可選的, 可以有1個(gè)或多個(gè)內(nèi)容體幀.
    特定通道上的內(nèi)容幀是嚴(yán)格有序的. 也就是說(shuō),它們可以和其它通道的幀混合,但同一個(gè)通道內(nèi)兩個(gè)幀是不可能混合或重疊, 也不可能出現(xiàn)單個(gè)內(nèi)容上的內(nèi)容幀與相同通道上的方法幀相混合.
    注意,任何非內(nèi)容幀都會(huì)明確地標(biāo)識(shí)內(nèi)容的結(jié)束. 盡管可從內(nèi)容頭中知道內(nèi)容的大小,但也允許發(fā)送者在不關(guān)閉通道的情況下中止內(nèi)容發(fā)送.
    實(shí)現(xiàn)者指導(dǎo)方針:
     收到不完整或錯(cuò)誤格式內(nèi)容的節(jié)點(diǎn)必須使用回復(fù)碼500(非希望幀)拋出一個(gè)連接異常. 這包括缺少內(nèi)容頭,內(nèi)容頭中錯(cuò)誤的class IDs,缺少內(nèi)容體幀等等.
    4.2.6.1 內(nèi)容頭
    內(nèi)容頭負(fù)載有下面的格式:

    實(shí)現(xiàn)者指導(dǎo)方針:
     class-id必須與方法幀class id匹配. 節(jié)點(diǎn)必須對(duì)無(wú)效的class-id使用501回復(fù)碼(幀錯(cuò)誤)拋出一個(gè)連接異常.
     weight字段未使用且必須是0.
     body大小是一個(gè)64位值,它定義了內(nèi)容體的總大小,也就是后面內(nèi)容體幀的body大小的總和. 0表示無(wú)內(nèi)容體幀.
     property flags是位數(shù)組,它表示每個(gè)屬性的存在性. 位是從最高到最低進(jìn)行排序的,位15代表第一個(gè)屬性.
     property flags可指定多于16屬性.如果最后位(0)被設(shè)置了,這表明其后有進(jìn)一步的屬性標(biāo)志字段。根據(jù)需要,這里有許多屬性標(biāo)志字段。
     屬性值是特定類的AMQP數(shù)據(jù)字段.
     位屬性僅由它們各自的屬性標(biāo)志(0或1)表示,并且在屬性列表中不存在。
     內(nèi)容幀中的通道編碼不能為0.在內(nèi)容幀中收到0通道編號(hào)的節(jié)點(diǎn)必須使用504回復(fù)碼(通道錯(cuò)誤)來(lái)發(fā)出異常信號(hào)
    4.2.6.2 內(nèi)容體
    內(nèi)容體負(fù)載是是不透明的二進(jìn)制塊,其后跟著一個(gè)結(jié)束幀字節(jié):

    內(nèi)容體可以根據(jù)需要分成多個(gè)幀.幀負(fù)載的最大大小可在連接時(shí),由兩端進(jìn)行協(xié)商.
    實(shí)現(xiàn)者指導(dǎo)方針:
     節(jié)點(diǎn)必須要能將分成多個(gè)幀的內(nèi)容體作為單一集合進(jìn)行存儲(chǔ)處理,要么分成更小的幀重新傳輸,要么 連接成單個(gè)塊分發(fā)給應(yīng)用程序.
    4.2.7 心跳幀
    心跳幀告訴收件人發(fā)件人仍然是活的. 在連接時(shí),心跳幀的速率和時(shí)間都可以調(diào)整.
    實(shí)現(xiàn)者指導(dǎo)方針:
     心跳幀的通道編號(hào)必須為0. 收到無(wú)效心跳幀的節(jié)點(diǎn)需使用501回復(fù)碼(幀錯(cuò)誤)來(lái)拋出異常.
     如果節(jié)點(diǎn)不支持心跳,它必須在不發(fā)出錯(cuò)誤或失敗信號(hào)的情況下丟棄心跳幀.
     client收到Connection.Tune方法后,必須要開(kāi)始發(fā)送心跳, 并在收到Connection.Open后,必須要開(kāi)始監(jiān)控.server在收到Connection.Tune-Ok后,需要開(kāi)始發(fā)送和監(jiān)控心跳.
     節(jié)點(diǎn)應(yīng)該盡最大努力按固定頻率來(lái)發(fā)送心跳. 心跳可在任何時(shí)候發(fā)送. 任何發(fā)送字節(jié)都可作為心跳的有效替代,因此當(dāng)超過(guò)固定頻率還沒(méi)有發(fā)送非AMQP心跳時(shí),必須發(fā)送心跳.如果節(jié)點(diǎn)在兩個(gè)心跳間隔或更長(zhǎng)時(shí)間內(nèi),未探測(cè)到傳入的心跳,它可在不遵循Connection.Close/Close-Ok握手的情況下,關(guān)閉連接,并記錄錯(cuò)誤信息.
     心跳應(yīng)該具有持續(xù)性,除非socket連接已經(jīng)被關(guān)閉, 包括在Connection.Close/Close-Ok 握手期間或之后的時(shí)間.
    4.3 通道復(fù)用
    AMQP 允許節(jié)點(diǎn)創(chuàng)建多個(gè)獨(dú)立的控制線程.每個(gè)通道都可作為共享單個(gè)socket的虛擬連接:

    實(shí)現(xiàn)者指導(dǎo)方針:
     AMQP節(jié)點(diǎn)可支持多個(gè)通道.在連接協(xié)商期間,可定義最大通道數(shù)目,節(jié)點(diǎn)可協(xié)商這個(gè)數(shù)值為1.
     每個(gè)節(jié)點(diǎn)都應(yīng)該以公平的方式平衡所有打開(kāi)通道的流量. 這種平衡可以每幀為基礎(chǔ),也可以以每個(gè)通道上的總交通流量為基礎(chǔ). 節(jié)點(diǎn)不應(yīng)該允許一個(gè)非常繁忙的通道讓一個(gè)不太繁忙的通道餓死.
    4.4 可見(jiàn)性保證
    服務(wù)器必須確保客戶端對(duì)服務(wù)器狀態(tài)的觀察是一致的。
    下面的示例說(shuō)明了在這種情況下,客戶端的觀察方法:
     Client 1 和 Client 2 連上了同一個(gè)虛擬主機(jī)
     Client 1 聲明了一個(gè)隊(duì)列
     Client 1 收到了Declare.Ok回復(fù) (觀察”的一個(gè)例子)
     Client 1 將其告知了Client 2
     Client 2 對(duì)同一個(gè)隊(duì)列做了被動(dòng)聲明
    可見(jiàn)性必須保證Client 2能看到隊(duì)列(在沒(méi)有刪除的情況下)
    4.5 通道關(guān)閉
    當(dāng)發(fā)生以下事件時(shí),server會(huì)考慮通道已經(jīng)關(guān)閉了:
    1. 節(jié)點(diǎn)關(guān)閉了通道或其父連接使用了Close/Close-Ok握手.
    2. 節(jié)點(diǎn)在通道或父連接上拋出了異常.
    3.節(jié)點(diǎn)未使用 Close/Close-Ok握手關(guān)閉了父連接socket.
    當(dāng)服務(wù)器關(guān)閉通道時(shí),通道上任何未應(yīng)答的消息將標(biāo)記為重新分發(fā).
    當(dāng)服務(wù)器關(guān)閉連接時(shí),它會(huì)刪除連接所擁有的自動(dòng)刪除信息.
    4.6 內(nèi)容同步
    在某些情況下,同步請(qǐng)求響應(yīng)方法會(huì)對(duì)同一個(gè)信道上的異步內(nèi)容傳遞產(chǎn)生影響,包括:
     Basic.Consume 和 Basic.Cancel 方法, 這些會(huì)啟動(dòng)和停止消息隊(duì)列中的消息流.
     Basic.Recover 方法,它會(huì)要求服務(wù)器重新分發(fā)消息到通道.
     Queue.Bind, Queue.Unbind, 和Queue.Purge 方法, 它會(huì)影響消息進(jìn)入消息隊(duì)列.
    實(shí)現(xiàn)者指導(dǎo)方針:
     請(qǐng)求-響應(yīng)效果在response方法之前必須不可見(jiàn),但在之后必須可見(jiàn).
    4.7 內(nèi)容排序保證
    流經(jīng)通道的方法順序是穩(wěn)定的:方法按發(fā)送時(shí)的順序接收. 這是由AMQP使用的TCP/IP傳輸所保證的.
    此外,服務(wù)器也會(huì)按一種穩(wěn)定的方式來(lái)處理內(nèi)容.尤其是,經(jīng)過(guò)服務(wù)器中單個(gè)路徑的內(nèi)容會(huì)保持順序.
    對(duì)于設(shè)定了優(yōu)先級(jí)并經(jīng)過(guò)單個(gè)路徑內(nèi)容,我們定義了一個(gè)內(nèi)容處理路徑-由一個(gè)傳入通道,一個(gè)交換器,一個(gè)隊(duì)列和一個(gè)傳出通道組成.
    實(shí)現(xiàn)者指導(dǎo)方針:
     server必須保持流經(jīng)單個(gè)內(nèi)容處理路徑上的順序性,除非在Basic.Deliver或Basic.Get-Ok方法上設(shè)置了redelivered字段,可根據(jù)條件規(guī)則來(lái)設(shè)置字段.
    4.8 錯(cuò)誤處理
    4.8.1 異常
    使用標(biāo)準(zhǔn)的異常編程模型, AMQP不會(huì)發(fā)出成功信號(hào),只在失敗時(shí)才發(fā)出信號(hào). AMQP定義了兩種異常級(jí)別:
    1. 通道異常.指那些關(guān)閉通道引起的錯(cuò)誤.通道異常通常是因?yàn)檐涘e(cuò)誤引起的,這些錯(cuò)誤并不影響應(yīng)用程序的其它部分.
    2. 連接異常. 這些關(guān)閉socket連接的異常通常是因?yàn)橛插e(cuò)誤造成的,如程序錯(cuò)誤,錯(cuò)誤配置或其他需要干預(yù)的情況。
    4.8.2 回復(fù)代碼格式
    AMQP 回復(fù)代碼按照 IETF RFC 2821的回復(fù)代碼的嚴(yán)重程度和理論進(jìn)行定義.
    4.9 限制
    AMQP規(guī)范為將來(lái)的AMQP擴(kuò)展或同種線路級(jí)格式使用了如下限制:
     每個(gè)連接上的通道數(shù)量: 16位通道數(shù)量.
     協(xié)議類數(shù)量: 16位class id.
     每個(gè)協(xié)議內(nèi)的方法數(shù)量: 16位 method id.
    AMQP規(guī)范對(duì)于數(shù)據(jù)做了如下限制:
     短字符串的最大長(zhǎng)度為: 255字節(jié).
     長(zhǎng)字符串或字段表的最大長(zhǎng)度: 32位大小.
     幀負(fù)載的最大大小: 32位大小
     內(nèi)容的最大長(zhǎng)度: 64位大小.
    服務(wù)器或客戶端也可以對(duì)資源施加自己的限制,如并發(fā)連接的數(shù)量、每個(gè)通道的消費(fèi)者數(shù)量、隊(duì)列的數(shù)量等。這些不影響互操作性,因此并沒(méi)有指定。
    4.10 安全
    4.10.1 目標(biāo)和原則
    為了防止緩沖區(qū)溢出,我們?cè)谒械胤蕉际褂锰囟ㄩL(zhǎng)度的緩沖區(qū). 當(dāng)讀取數(shù)據(jù)時(shí),所有數(shù)據(jù)都可以使用允許的最大長(zhǎng)度來(lái)進(jìn)行驗(yàn)證.無(wú)效的數(shù)據(jù)可以被明確地處理,通過(guò)關(guān)閉通道或連接。
    4.10.2 拒絕服務(wù)攻擊
    AMQP 通過(guò)回復(fù)碼并關(guān)閉通道或連接來(lái)處理錯(cuò)誤.這避免了錯(cuò)誤出現(xiàn)后的模糊狀態(tài).在連接協(xié)商期間,服務(wù)器可假設(shè)特殊條件是因獲取訪問(wèn)服務(wù)器的敵對(duì)嘗試所造成的.對(duì)于連接協(xié)商中的任何異常,一般處理是暫停該連接 (可能是一個(gè)線程)幾秒種時(shí)間,然后再關(guān)閉網(wǎng)絡(luò)連接. 這包括語(yǔ)法錯(cuò)誤,過(guò)大數(shù)據(jù),或認(rèn)證失敗.服務(wù)器應(yīng)該記錄所有這些異常標(biāo)志或阻止客戶端挑起多個(gè)故障.
    posted on 2016-08-12 18:30 胡小軍 閱讀(10848) 評(píng)論(0)  編輯  收藏 所屬分類: RabbitMQ
    主站蜘蛛池模板: 57pao国产成视频免费播放| 久久久国产精品福利免费| 一区二区免费国产在线观看| 国产精品黄页免费高清在线观看| 亚洲AV一二三区成人影片| 亚洲狠狠色丁香婷婷综合| 亚洲av永久无码一区二区三区| 亚洲一级高清在线中文字幕| 亚洲精品理论电影在线观看| 一级毛片在线完整免费观看| 久久一区二区三区免费播放 | A毛片毛片看免费| 日韩电影免费在线观看网站| 国产精品免费观看| 免费人成年轻人电影| 亚洲国产另类久久久精品| 亚洲人成日本在线观看| 国产偷国产偷亚洲高清人| 中文字幕免费观看全部电影| 最近免费中文字幕大全免费| 四虎成人免费大片在线| 亚洲精品夜夜夜妓女网| 亚洲AV一二三区成人影片| 一级毛片在线播放免费| 亚洲免费电影网站| 免费a级毛片在线观看| 亚洲成a人片在线观看中文动漫| 亚洲AV成人片色在线观看高潮| 亚洲国产精品无码专区| 亚洲综合一区国产精品| h视频在线观看免费| 99久久免费国产香蕉麻豆| 亚洲成av人在片观看| 亚洲综合久久综合激情久久| 亚洲1区2区3区精华液| 和老外3p爽粗大免费视频| 91免费精品国自产拍在线不卡| 色视频色露露永久免费观看| 亚洲av无码专区在线播放| 亚洲精品色播一区二区| 久久久久久久岛国免费播放|