1. 程式人生 > >架構設計:系統間通訊——MQ:訊息協議

架構設計:系統間通訊——MQ:訊息協議

1、概述

從本文開始,我們介紹另一型別的系統間通訊及輸:MQ訊息佇列。首先我們將討論幾種常用訊息佇列協議的基本原理和工作方式,包括MQTT、XMPP、Stomp、AMQP、OpenWire等。然後在這個基礎上介紹兩款MQ產品:ActiveMQ和RabbitMQ,它們是現在業務系統中應用廣泛的訊息佇列軟體。包括他們的安裝、執行、支援協議、叢集化和呼叫方式。

當然,在這個過程中我們還會提到其他的訊息佇列協議(或者實現),例如微軟JBossMQ、MSMQ、商業化產品WebSphere MQ、Oracle高階佇列(AQ)等。我們還會討論這些眼花繚亂的協議、軟體、程式庫之間的關係

隨後我們會花一些篇幅,討論現在新興的訊息佇列Kafka和ZeroMQ。它們的應用越來越廣泛,尤其在大資料的採集方面。最後我們將使用訊息佇列搭建一個高效能的日誌採集系統,作為實戰。

2、基本概念

2-1、訊息

首先有三個基本概念在開篇前我們需要進行討論:訊息、訊息協議、訊息佇列。訊息既是資訊的載體 這個描述相信各位讀者都能夠明白。為了讓訊息傳送者和訊息接收者都能夠明白訊息所承載的資訊(訊息傳送者需要知道如何構造訊息;訊息接收者需要知道如何解析訊息),它們就需要按照一種統一的格式描述訊息,這種統一的格式稱之為訊息協議。所以,有效的訊息一定具有某一種格式;而沒有格式的訊息是沒有意義的

而訊息從傳送者到接收者的方式也有兩種。一種我們可以稱為即時訊息通訊,也就是說訊息從一端發出後(訊息傳送者)立即就可以達到另一端(訊息接收者),這種方式的具體實現就是我們已經介紹過的RPC(當然單純的http通訊也滿足這個定義);另一種方式稱為延遲訊息通訊

,即訊息從某一端發出後,首先進入一個容器進行臨時儲存,當達到某種條件後,再由這個容器傳送給另一端。 這個容器的一種具體實現就是訊息佇列

2-2、知識結構

訊息佇列和已經介紹過的RPC相同的是:無論是RPC也好,訊息佇列也好他們都建立在網路IO模型基礎上(我們已經介紹過多種網路IO模型)。先進的網路IO模型將賦予MQ協議優異的效能表現(當然,效能也不僅僅取決於網路IO模型)。

這裡寫圖片描述

從上圖可以看到,某一種訊息通訊軟體(或者叫做程式庫)的實現都建立在“協議”基礎上:RMI程式庫建立在RMI協議上(RMI協議是JAVA規範協議的一部分) ,屬於一種“即時訊息通訊”;RabbitMQ和Qpid訊息通訊軟體的設計依據是AMQP協議,屬於一種“延遲訊息通訊”。

雖然訊息協議存在“私有協議”和“開放協議”之分(是否向行業開放訊息規範文件、是否允許某個組織更改協議),雖然某一個軟體(程式庫)不一定只支援一種協議(例如ActiveMQ實現了多種訊息協議),雖然某一種協議也不一定只有一種軟體(程式庫)實現(例如能夠支援webservice協議的程式庫就有Codehaus XFire、Apache CXF、Jboss RESTEasy等),但是這並不影響“某一種訊息通訊軟體(或者叫做程式庫)的實現都建立在“協議”基礎上”的概念,反而是這個基本概念加強了。

3、訊息協議

那麼要理解訊息佇列,我們就應該從這些支援“延遲訊息通訊”的訊息協議開始討論。這個小節我們首先為各位讀者介紹幾種使用的訊息協議,他們是XMPP、Stomp和AMQP。為了承接後文我們講解的MQ軟體,這三個協議中我們又著重講解AMQP協議。

3-1、XMPP協議

3-1-1、定義

XMPP is the Extensible Messaging and Presence Protocol, a set of open technologies for instant messaging, presence, multi-party chat, voice and video calls, collaboration, lightweight middleware, content syndication, and generalized routing of XML data.

以上內容引用自XMPP官網,這個定義已經可以清楚表明XMPP協議的用途和特性。XMPP的前身是Jabber,一個開源形式組織制定的網路即時通訊協議。XMPP目前被IETF國際標準組織完成了標準化工作。

XMPP基於XML,用於IM系統的開發。國內比較流行的XMPP伺服器叫做Openfire,它使用MINA作為下層的網路IO框架(不是MINA2是MINA1);國外用的比較多的XMPP伺服器叫做Tigase,它的官網號稱單節點可以支撐50萬用戶線上,叢集可以支援100萬用戶線上:(http://projects.tigase.org/

Cluster with over 1mn online users . 500k online users on a single machine

當然如果讀者所在公司需要開發IM系統,除了使用現成的XMPP伺服器以外,還需要實現了XMPP協議的客戶端或者開發包(以便進行擴充套件開發)。您可以在XMPP官網檢視到XMPP官方推薦的開發包,各種語言的支援基本上都有:http://xmpp.org/software/libraries.html

筆者曾參與過某幾款IM系統的開發(包括自己創業的專案),總的來說XMPP協議本身是不錯的選擇,但是學習起來會耗費相當的時間,並且某些XMPP客戶端、伺服器端或者程式庫並沒有這些開發團隊宣傳的那麼穩定好用。所以如果您的公司需要進行IM系統的開發,那麼創立私有的訊息協議也會是一個不錯的選擇

3-1-2、協議通訊過程示例

為了讓各位讀者對XMPP協議有一個感性認識,這裡我們給出一個XMPP協議處理“IM使用者登入”操作的過程(XMPP的登入方式分為有使用者密碼和無使用者密碼兩種方式,這裡我們介紹無密碼登入方式)。

XMPP協議本身細節比較豐富,這裡我們只討論登入操作,如果讀者有興趣可以下載全套的XMPP官方規範文件進行研究(http://xmpp.org/):

這裡寫圖片描述

通過上圖可以看到,XMPP協議中的xml片段。這裡出現了幾個XMPP協議中的關鍵資訊,例如:

  • stream標記:通訊流標記,是指XMPP的客戶端或者伺服器端向對方發起的通訊請求(或者響應)。通訊流並不攜帶正真的內容資訊,指示表明客戶端和伺服器端發生了一次互動。stream的屬性包括:to、from、id、xml:lang、version等。

  • iq標記:iq標記是Info/Query的簡稱(你可以理解成查詢資訊請求),一般是一組的形式出現,由客戶端發起查詢請求,由伺服器端返回查詢結果。由於查詢請求的型別不一樣,iq標記中可以嵌入的子標記就有很多。例如,可以嵌入bind標記,表明某個使用者和jid的繫結關係;可以嵌入多個item標記,表明查詢得到的這個使用者的好友資訊(如下)。

<iq to='[email protected]/someresource' type='result' id='roster'>  
    <query xmlns='jabber:iq:roster'>  
        <item jid='[email protected]' name='someone1'/>  
        <item jid='[email protected]' name='someone2'/>  
    </query>  
</iq>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • jid標記:jid(JabberID)是XMPP協議中標示,它用來標示XMPP網路中的各個XMPP實體(實體可以是某一個使用者、某一個伺服器、某一個聊天室),規範格式如下:
jid = [ node "@" ] domain [ "/" resource ] 
  • 1
  • 還有未出現的message、presence標記:message是實體內容標記,記錄了聊天的真實內容;presence標記表示了XMPP使用者的服務狀態(離線,線上、忙碌等)。示例如下:
<message to="[email protected]/someresource" type="chat"> 
    <body>helloword。。。</body> 
</message> 
  • 1
  • 2
  • 3

3-2、Stomp協議

3-2-1、定義

Stomp協議,英文全名Streaming Text Orientated Message Protocol,中文名稱為 ‘流文字定向訊息協議’。是一種以純文字為載體的協議(以文字為載體的意思是它的訊息格式規範中沒有類似XMPP協議那樣的xml格式要求,你可以將它看作‘半結構化資料’)。目前Stomp協議有兩個版本:V1.1和V1.2。

一個標準的Stomp協議包括以下部分:命令/資訊關鍵字、頭資訊、文字內容。如下圖所示:

這裡寫圖片描述

以下為一段簡單的協議資訊示例:

CONNECT
accept-version:1.2
someparam1:value1
someparam2:value2

this is conntecon ^@
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

上面的示例中,我們使用了Stomp協議的CONNECT命令,它的意思為連線到Stomp代理端,並且攜帶了要求代理端的版本資訊和兩個自定義的K-V資訊(請注意’^@’符號,STOMP協議中用它來表示NULL)。

Stomp協議中有兩個重要的角色:STOMP客戶端與任意STOMP訊息代理(Broker)。如下圖所示:

這裡寫圖片描述

看了上面的示意圖後有的讀者可能會問:為什麼稱為Stomp訊息代理,而不稱為Stomp訊息服務?因為Stomp Broker只是負責接受和儲存客戶端發來的訊息、只是按照客戶端要求的路徑轉發訊息,只是管理客戶端連線和訂閱:它並不負責根據訊息內容做任何業務處理。所以將它稱為訊息代理端更貼切。

由於Stomp協議的結構如此簡單,以至於任何理解Stomp協議命令格式的技術人員都可以開發Stomp的代理端或者Stomp的客戶端,並將自己滿足Stomp協議的系統輕鬆接入另一個同樣滿足Stomp協議的第三方系統(例如activeMQ)

3-2-2、基本命令/返回資訊

和介紹XMPP協議的方式類似,為了讓讀者對Stomp協議有進一步的認識,本小節我們介紹Stomp協議的基本命令和代理端返回的資訊種類,並且列舉一些例項進行使用講解。

在Stomp協議中,主要有以下命令/返回資訊(有的文章中也稱一個完整的資訊為幀)。這些命令/返回資訊構成了Stomp協議的主體,並能夠支援您的Stomp客戶端和Stomp代理端完成連線、傳送、訂閱、事務、響應的整個操作過程。這些命令/返回是:

  • CONNECT/STOMP命令: 客戶端通過使用CONNECT命令,連線到Stomp代理端。如果使用STOMP命令,那麼Stomp代理端的版本必須是1.2。

  • CONNECTED資訊:當Stomp代理端收到客戶端傳送來的Connect命令並且處理成功後,將向這個客戶端返回CONNECTED狀態資訊;如果這個過程中出現任何問題,還可能返回ERROR資訊

  • SEND 傳送命令:客戶端使用SEND命令,向某個指定位置(代理端上的一個虛擬路徑)傳送內容。這樣在這個路徑上訂閱了訊息事件的其它客戶端,將能夠收到這個訊息。

  • SUBSCRIBE 訂閱命令:客戶端使用SUBSCRIBE訂閱命令,向Stomp服務代理訂閱某一個虛擬路徑上的監聽。這樣當其它客戶端使用SEND命令傳送內容到這個路徑上時,這個客戶端就可以收到這個訊息。在使用SUBSCRIBE時,有一個重要的ACK屬性。這個ACK屬性說明了Stomp服務代理端傳送給這個客戶端的訊息是否需要收到一個ACK命令,才認為這個訊息處理成功了。如下所示:

SUBSCRIBE
id:XXXXXXXXX
destination:/test
ack:client

^@
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

以上SUBSCRIBE命令資訊說明,客戶端訂閱的虛擬位置是test。且命令資訊中ack屬性為client,說明當客戶端收到訊息時,必須向代理端傳送ack命令,代理端才認為這個訊息處理成功了(ack的值只有三種:auto(預設)、client和client-individual)。

  • UNSUBSCRIBE 退訂命令:客戶端使用這個命令,取消對某個路徑上訊息事件的監聽。如果客戶端給出的路徑之前就沒有被這個客戶端訂閱,那麼這個命令執行無效。

  • MESSAGE 資訊:當客戶端在某個訂閱的位置收到訊息時,這個訊息將通過MESSAGE關鍵字進行描述。類似以下資訊就是從代理端拿到的訊息描述:

MESSAGE
redelivered:true
message-id:ID:localhost-34450-1457321490460-4:24:-1:1:1
destination:/test
timestamp:1457331607873
expires:0
priority:4

2345431457331607861
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • BEGIN 開始事務命令: Stomp協議支援事務模式,在這種模式下,使用Send命令從某個客戶端發出的訊息,在沒有使用COMMIT正式提交前,這些訊息是不會真正傳送給Stomp代理端的。BEGIN命令就是用於開啟事務。注意,一個事務中可以有一條訊息,也可以有多條訊息

  • COMMIT 提交命令: 當完成事務中的資訊定義後,使用該命令提交事務。只有使用COMMIT命令後,在某一個事務中的一條或者多條訊息才會進入Stomp代理端的佇列(訂閱了事件的其它客戶端才能收到這些訊息)。

  • ABORT 取消/終止事務命令:很明顯,這個命令用於取消/終止當前還沒有執行COMMIT命令的事務。

  • ACK 確認命令:當客戶端使用SUBSCRIBE命令進行訂閱時,如果在SUBSCRIBE命令中制定ack屬性為client,那麼這個客戶端在收到某條訊息(id為XXXX)後,必須向Stomp代理端傳送ACK命令,這樣代理端才會認為訊息處理成功了;如果Stomp客戶端在斷開連線之前都沒有傳送ACK命令,那麼Stomp代理端將在這個客戶端斷開連線後,將這條訊息傳送給其它客戶端

ACK
id:MESSAGE ID

^@
  • 1
  • 2
  • 3
  • 4

請注意head部分的id屬性,傳遞的id屬性是之前收到的MESSAGE資訊的id標示。

  • NACK 不確認命令:同樣是以上的SUBSCRIBE命令的狀態下,如果這時Stomp客戶端向Stomp代理端傳送NACK資訊,證明這條訊息在這個客戶端處理失敗。Stomp代理端將會把這條訊息傳送給另一個客戶端(無論當前的客戶端是否斷開連線)

  • DISCONNECT 斷開命令:這個命令將斷開Stomp客戶端與Stomp代理端的連線。

上篇文章中我們重點討論了“協議”的重要性,併為各位讀者介紹了Stomp協議和XMPP協議。這兩種協議是訊息佇列中兩種不同使用場景下的典型代表。本文主要接續上文的篇幅,繼續討論訊息佇列中另一種典型協議:AMQP協議。

3-3、AMQP協議

AMQP協議的全稱是:Advanced Message Queuing Protocol(高階訊息佇列協議)。目前AMQP協議的版本為 Version 1.0,這個協議標準在2014年通過了國際標準組織 (ISO) 和國際電工委員會 (IEC) 的投票,成為了新的 ISO 和 IEC 國際化標準。目前支援AMQP的軟體廠商包括:

這裡寫圖片描述

3-3-1、協議概覽

在網路上講解AQMP協議的文章已經有很多了,您可以在百度、Google、必應上搜索關鍵字‘AMQP’,就會出現很多相關文章。雖然文章數量比較多,但是卻鮮有質量過硬的文章(當然除了AMQP官網 http://www.amqp.org/ 的協議說明文件)。本小節的內容我試圖在能力所及的範圍內,為各位讀者將AMQP協議的核心要點講清楚。為了達到這個目的,首先將AMQP協議的原理用下圖進行一個全面呈現,然後在詳細講解圖中的每一個要點:

這裡寫圖片描述

從上圖我們可以看到AMQP協議的各個組成部分:

  • AMQP協議中的元素包括:Message(訊息體)、Producer(訊息生產者)、Consumer(訊息消費者)、Virtual Host(虛擬節點)、Exchange(交換機)、Queue(佇列)等

  • 由Producer(訊息生產者)和Consumer(訊息消費者)構成了AMQP的客戶端,他們是傳送訊息和接收訊息的主體。AMQP服務端稱為Broker,一個Broker中一定包含完整的Virtual Host(虛擬主機)、 Exchange(交換機)、Queue(佇列)定義。

  • 一個Broker可以建立多個Virtual Host(虛擬主機),我們將討論的Exchange和Queue都是虛擬機器中的工作元素(還有User元素)。注意,如果AMQP是由多個Broker構成的叢集提供服務,那麼一個Virtual Host也可以由多個Broker共同構成。

  • Connection是由Producer(訊息生產者)和Consumer(訊息消費者)建立的連線,連線到Broker物理節點上。但是有了Connection後客戶端還不能和伺服器通訊,在Connection之上客戶端會建立Channel,連線到Virtual Host或者Queue上,這樣客戶端才能向Exchange傳送訊息或者從Queue接受訊息。一個Connection上允許存在多個Channel,只有Channel中能夠傳送/接受訊息

  • Exchange元素是AMQP協議中的交換機,Exchange可以繫結多個Queue也可以同時繫結其他Exchange。訊息通過Exchange時,會按照Exchange中設定的Routing(路由)規則,將訊息傳送到符合的Queue或者Exchange中

那麼AMQP訊息在這個結構中是如何通過Producer發出,又經過Broker最後到達Consumer的呢?請看下圖:

這裡寫圖片描述

  1. 在Producer(訊息生產者)客戶端建立了Channel後,就建立了到Broker上Virtual Host的連線。接下來Producer就可以向這個Virtual Host中的Exchange傳送訊息了。

  2. Exchange(交換機)能夠處理訊息的前提是:它至少已經和某個Queue或者另外的Exchange形成了繫結關係,並設定好了到這些Queue和Excahnge的Routing(路由規則)。Excahnge中的Routing有三種模式,我們隨後會講到。在Exchange收到訊息後,會根據設定的Routing(路由規則),將訊息傳送到符合要求的Queue或者Exchange中(路由規則還會和Message中的Routing Key屬性配合使用)。

  3. Queue收到訊息後,可能會進行如下的處理:如果當前沒有Consumer的Channel連線到這個Queue,那麼Queue將會把這條訊息進行儲存直到有Channel被建立(AMQP協議的不同實現產品中,儲存方式又不盡相同);如果已經有Channel連線到這個Queue,那麼訊息將會按順序被髮送給這個Channel。

  4. Consumer收到訊息後,就可以進行訊息的處理了。但是整個訊息傳遞的過程還沒有完成:視設定情況,Consumer在完成某一條訊息的處理後,將需要手動的傳送一條ACK訊息給對應的Queue(當然您可以設定為自動傳送,或者無需傳送)。Queue在收到這條ACK資訊後,才會認為這條訊息處理成功,並將這條訊息從Queue中移除;如果在對應的Channel斷開後,Queue都沒有這條訊息的ACK資訊,這條訊息將會重新被髮送給另外的Channel。當然,您還可以傳送NACK資訊,這樣這條訊息將會立即歸隊,併發送給另外的Channel

3-3-2、Message(訊息體)

通過上一小節的描述,我們可以看到AMQP協議中訊息的處理規則和Stomp協議中訊息的處理規則有類似之處,比如對ACK、NACK的使用。但明顯不同的地方還是很多,例如AMQP中Exchange元素提供的Routing路由規則,這顯然比Stomp協議中直接傳送給Queue要靈活得多。

為了支援AMQP協議中的這些規則,AMQP協議中的訊息也必須有特定的格式,實際上AMQP協議要比Stomp協議複雜得多。下面我們就根據ISO/IEC釋出的AMQP Version 1.0標準文件,來討論一下AMQP協議中的訊息格式。

首先要說明的是目前國內多個技術站點,詳細介紹AMQP訊息格式的文章本來就不多(不包括那些聊聊幾筆的轉發),而且基本上都沒有詳細講解格式本身,只是粗略說明了AMQP訊息採用二進位制格式(任何應用層協議在網路上進行傳輸,都是使用二進位制流進行的,所以這個說法當然沒錯)。

有的文章還向讀者傳遞了錯誤的資訊。例如說AMQP訊息格式包括兩部分:訊息頭和訊息正文。 這是完全錯誤的,雖然AMQP訊息格式確實包括Header和Body部分,但是絕對不止這兩個部分。(如果真是這樣,ISO/IEC組織就不需要使用125頁的文件篇幅來進行說明了)

首先我們需要說明的是,作為一種網路通訊協議,AMQP工作在七層/五層網路模型的應用層,是一個典型的應用層協議;另外,由於AMQP協議存在多種元素定義,且這些元素定義工作在不同的領域。例如Channel的定義是為了基於網路連線記錄會話狀態;Queue等元素幫助AMQP完成路由規則,這些元素在Message訊息記錄中都需要有所體現。

所以AMQP協議首先要記錄網路狀態和會話狀態,格式如下(AMQP幀的定義在《OASIS Advanced Message Queueing Protocol
(AMQP) Version 1.0》文件的第38頁):

這裡寫圖片描述

其中非PAYLOAD部分,在網路協議的應用層說明Channel的工作狀態(當然還有說明整個AMQP訊息的長度區域:SIZE),我們真正需要的內容存在PAYLOAD區域。PAYLOAD區域(譯文稱為‘交付區’)的格式如下(可以在《OASIS Advanced Message Queueing Protocol
(AMQP) Version 1.0》文件的第3部分:messaging第82頁找到詳細說明):

這裡寫圖片描述

在PAYLAOD區域一共包含7個數據區域:header、delivery-annotations、message-annotations、properties、application-properties、application-data、footer。這些元素的作用如下:

  • header:header部分記錄了AMQP訊息的在‘支援AMQP的中介軟體’中的互動狀態。例如該條訊息在節點間被互動的總次數、優先順序、TTL(Time To Live)值等資訊。

  • delivery-annotations:在header部分只能傳遞規範的、標準的、經過ISO/IEC組織定義的屬性。那麼如果需要在header部分傳遞一些非標準資訊怎麼辦呢?這就是delivery-annotations資料區域存在的意義:用來記錄那些’非標’的header資訊。

  • message-annotations:這個資料區域,用於儲存一些自定義的輔助屬性。和delivery-annotations區域的非標準資訊不同,這裡的自定義屬性主要用於訊息的轉換。例如AMQP-JMS資訊轉換過程中將依據這個資料區域的“x-opt-jms-type”、“x-opt-to-type”、“x-opt-reply-type”和“name”屬性進行JMS規範中對應的“JMSType”、“Type of the JMSDestination”、“Type of the JMSReplyTo”和“JMS_AMQP_MA_name”屬相的轉換。

  • properties:從整個AMQP訊息的properties屬性開始,到AMQP訊息的application-data部分結束,才是AMQP訊息的正文內容(譯文稱為‘裸訊息’)。Properties屬性記錄了AMQP訊息正文的那些‘不可變’屬性。在properties部分只能傳遞規範的、標準的、經過ISO/IEC組織定義的屬性。例如:訊息id、分組id、傳送者id、內容編碼等。以下是AMQP協議文件中對Properties部分屬性的描述(只能包含這些資訊):

<type name="properties" class="composite" source="list" provides="section">
    <descriptor name="amqp:properties:list" code="0x00000000:0x00000073"/>
    <field name="message-id" type="*" requires="message-id"/>
    <field name="user-id" type="binary"/>
    <field name="to" type="*" requires="address"/>
    <field name="subject" type="string"/>
    <field name="reply-to" type="*" requires="address"/>
    <field name="correlation-id" type="*" requires="message-id"/>
    <field name="content-type" type="symbol"/>
    <field name="content-encoding" type="symbol"/>
    <field name="absolute-expiry-time" type="timestamp"/>
    <field name="creation-time" type="timestamp"/>
    <field name="group-id" type="string"/>
    <field name="group-sequence" type="sequence-no"/>
    <field name="reply-to-group-id" type="string"/>
</type>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • application-properties:‘應用資料’屬性,在這部分資料中主要記錄和應用有關的資料,AMQP的實現產品(例如RabbitMQ)需要用這部分資料決定其處理邏輯。例如:送入哪一個Exchange、訊息的Routing值是什麼、是否進行持久化等。

  • application-data:使用二進位制格式描述的AMQP訊息的使用者部分內容。既是我們傳送出去的真實內容

  • footer:一般在這個資料區域儲存輔助內容,例如訊息的雜湊值,HMAC,簽名或者加密細節。

以上才是一個AMQP訊息的完整結構。當然由於篇幅限制,在某一個數據區域的‘標準’屬性就沒有再細講了,例如Properties資料區域定義的creation-time屬性、Header資料區域定義的durable屬性。有興趣的朋友可以參考《OASIS Advanced Message Queueing Protocol
(AMQP) Version 1.0》,這個文件我已經上傳到我的下載列表中,供大家免費下載^_^(http://download.csdn.net/detail/yinwenjie/9460653)。

3-3-3、Exchange(交換機)路由規則

Exchange交換機在AMQP協議中主要負責按照一定的規則,將收到的訊息轉發到已經和它事先繫結好的Queue或者另外的Exchange中。Excahnge交換機的這個處理過程稱之為Routing(路由)。目前流行的AMQP路由實現一共有三種:分別是Direct Exchange、Fanout Exchange和Topic Exchange。需要特別注意的是:Exhange需要具備怎樣的‘路由’規則,並沒有在AMQP標準協議進行強行規定,目前流行的AMQP轉發規則都是AMQP實現產品自行開發的(這也是為什麼AMQP訊息中和路由、過濾規則相關的屬性是存放在application-properties區域的原因)。

A、Direct路由

direct模式從字面上的理解應該是‘引導’、‘直接’的含義。direct模式下Exchange將使用AMQP訊息中所攜帶的Routing-Key和Queue中的Routing Key進行比較。如果兩者完全匹配,就會將這條訊息傳送到這個Queue中。如下圖所示:

這裡寫圖片描述

B、Fanout路由

Fanout路由模式不需要Routing Key。當設定為Fanout模式的Exchange收到AMQP訊息後,將會將這個AMQP訊息複製多份,分別傳送到和自己繫結的各個Queue中。如下圖所示:

這裡寫圖片描述

C、Topic路由

Topic模式是Routing Key的匹配模式。Exchange將支援使用‘#’和‘ * ’萬用字元進行Routing Key的匹配查詢(‘#’表示0個或若干個關鍵詞,‘ * ’表示一個關鍵詞,注意是關鍵詞不是字母)。如下圖所示:

這裡寫圖片描述

為了方便各位讀者的理解,這裡我們再舉幾個萬用字元匹配的示例:

  • “param.#”,可以匹配“param”、“param.test”、“param.value”、“param.test.child”等等AMQP訊息的Routing Key;但是不能匹配諸如“param1.test”、“param2.test”、“param3.test”。以為param這個關鍵詞和param1這個關鍵詞不相同。

  • “param.*.* ”,可以匹配“param.test.test”、“param.test.value”、“param.test.child”等等AMQP訊息的Routing Key;但是不能匹配諸如“param”、“param.test”、“parm.child”等等Routing Key。

  • “param.*.value”,可以匹配“param.value.value”、“param.test.value”等Routing Key;但是不能匹配諸如“param.value”、“param.value.child”等Routing Key。

注意,以上介紹的Direct 路由模式和Topic 路由模式中,如果Exchange交換機沒有找到任何匹配Routing Key的Queue,那麼這條AMQP訊息會被丟棄。(只有Queue有儲存訊息的功能,但是Exchange並不負責儲存訊息)

4、不得不提的JMS規範

JMS不是訊息佇列,更不是某種訊息佇列協議。**JMS是Java訊息服務介面,是一套規範的JAVA API 介面。這套規範介面由SUN提出,並在2002年釋出JMS規範的Version 1.1版本。**JMS和訊息中介軟體廠商無關,既然是一套介面規範,就代表這它需要各個廠商進行實現。好訊息是,大部分訊息中介軟體產品都支援JMS 介面規範。也就是說,您可以使用JMS API來連線Stomp協議的產品(例如ActiveMQ)。就像您可以使用JDBC API來連線ORACLE或者MYSQL一樣。

部分網路上的資料都介紹JMS是一個訊息佇列,這個說法是錯誤的,會誤導讀者。難道你能說JDBC是資料庫?

當然,這些具體實現JMS規範的JAVA API都是由具體的中介軟體廠商提供的。下面一段程式碼演示瞭如何使用JMS建立與ActiveMQ的連線:

package com.yinwenjie.test.testActivemq.jms;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;

/**
 * 測試使用JMS API連線ActiveMQ
 * @author yinwenjie
 */
public class JMSProducer {
    /**
     * 由於是測試程式碼,這裡忽略了異常處理。
     * 正是程式碼可不能這樣做
     * @param args
     * @throws RuntimeException
     */
    public static void main (String[] args) throws Exception {
        // 定義JMS-ActiveMQ連線資訊
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616", "username", "password");
        Session session = null;
        Destination sendQueue;
        Connection connection = null;

        //進行連線
        connection = connectionFactory.createConnection();
        connection.start();

        //建立會話
        session = connection.createSession(true, Session.SESSION_TRANSACTED);
        //建立queue(當然如果有了就不會重複建立)
        sendQueue = session.createQueue("");
        //建立訊息傳送者物件
        MessageProducer sender = session.createProducer(sendQueue);
        TextMessage outMessage = session.createTextMessage();
        outMessage.setText("這是傳送的訊息內容");

        //傳送(JMS是支援事務的)
        sender.send(outMessage);
        session.commit();

        //關閉
        sender.close();
        connection.close();
        connectionFactory.close();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

這裡,再給各位讀者一個官方文件。這個官方文件用於描述ActiveMQ訊息中介軟體中實現的AMQP協議資訊轉換為JMS服務介面能夠識別的資料資訊(請仔細理解這句話黑體字部分的描述)。http://activemq.apache.org/amqp.html

5、後文介紹

通過兩篇文章的篇幅,我們介紹了典型的訊息佇列協議。當然還有很多具體的訊息佇列協議沒有講到,但是通過介紹XMPP、AMQP、Stomp協議可以起到一個管中窺豹可見一斑的效果。另外我們還說明了JMS規範的具體含義,以便幫助讀者糾正一些不正確的觀點。

下一篇文章開始,我們將講解兩個典型的訊息佇列中介軟體:ActiveMQ和RabbitMQ。最後我們還會列舉一個實際場景,然後通過訊息佇列技術一起搭建一個高效能的業務處理方案。


相關推薦

架構設計系統通訊——MQ訊息協議

1、概述從本文開始,我們介紹另一型別的系統間通訊及輸:MQ訊息佇列。首先我們將討論幾種常用訊息佇列協議的基本原理和工作方式,包括MQTT、XMPP、Stomp、AMQP、OpenWire等。然後在這個基礎上介紹兩款MQ產品:ActiveMQ和RabbitMQ,它們是現在業務系

架構設計系統通訊(36)——Apache Camel快速入門(上)

架構設計:系統間通訊(36)——Apache Camel快速入門(上) :http://blog.csdn.net/yinwenjie(未經允許嚴禁用於商業用途!) https://blog.csdn.net/yinwenjie/article/details/51692340 1、本專題主

架構設計系統通訊(34)——被神化的ESB(上)

1、概述 從本篇文章開始,我們將花一到兩篇的篇幅介紹ESB(企業服務匯流排)技術的基本概念,為讀者們理清多個和ESB技術有關名詞。我們還將在其中為讀者闡述什麼情況下應該使用ESB技術。接下來,為了加深讀者對ESB技術的直觀理解,我們將利用Apache Came

架構設計系統通訊(16)——服務治理與Dubbo 中篇(預熱)

1、前序 上篇文章中(《架構設計:系統間通訊(15)——服務治理與Dubbo 上篇》),我們以示例的方式講解了阿里DUBBO服務治理框架基本使用。從這節開始我們將對DUBBO的主要模組的設計原理進行講解,從而幫助讀者理解DUBBO是如何工作的。(由於這個章節的內容比較多,包括了知識準備、DUBBO框架概述

架構設計系統通訊(6)——IO通訊模型和Netty 上篇

1、Netty介紹 在Netty官網上,對於Netty的介紹是: Netty is a NIO client server framework which enables quick and easy development of network ap

架構設計系統通訊(23)——提高ActiveMQ工作效能(中)

6、ActiveMQ處理規則和優化 在ActiveMQ單個服務節點的優化中,除了對ActiveMQ單個服務節點的網路IO模型進行優化外,生產者傳送訊息的策略和消費者處理訊息的策略也關乎整個訊息佇列系統是否能夠高效工作。請看下圖所示的訊息生產者和訊息消費

架構設計系統通訊(15)——服務治理與Dubbo 上篇

1、上篇中“自定義服務治理框架”的問題 在之前的文章中(《架構設計:系統間通訊(13)——RPC例項Apache Thrift 下篇(1)》、《架構設計:系統間通訊(14)——RPC例項Apache Thrift 下篇(2)》),我們基於服務治理的基本原理,自

架構設計系統通訊(21)——ActiveMQ的安裝與使用

1、前言 之前我們通過兩篇文章(架構設計:系統間通訊(19)——MQ:訊息協議(上)、架構設計:系統間通訊(20)——MQ:訊息協議(下))從理論層面上為大家介紹了訊息協議的基本定義,並花了較大篇幅向讀者介紹了三種典型的訊息協議:XMPP協議、Stomp協議和

架構設計系統通訊(10)——RPC的基本概念

1、概述 經過了詳細的資訊格式、網路IO模型的講解,並且通過JAVA RMI的講解進行了預熱。從這篇文章開始我們將進入這個系列博文的另一個重點知識體系的講解:RPC。在後續的幾篇文章中,我們首先講解RPC的基本概念,一個具體的RPC實現會有哪些基本要素構成,然

架構設計系統通訊(40)——自己動手設計ESB(1)

1、概述 在我開始構思這幾篇關於“自己動手設計ESB中介軟體”的文章時,曾有好幾次動過放棄的念頭。原因倒不是因為對冗長的文章產生了惰性,而是ESB中所涉及到的技術知識和需要突破的設計難點實在是比較多,再冗長的幾篇博文甚至無法對它們全部進行概述,另外如果在思路上

架構設計系統通訊(39)——Apache Camel快速入門(下2)

4-2-1、LifecycleStrategy LifecycleStrategy介面按照字面的理解是一個關於Camel中元素生命週期的規則管理器,但實際上LifecycleStrategy介面的定義更確切的應該被描述成一個監聽器: 當Camel

架構設計系統通訊(24)——提高ActiveMQ工作效能(下)

7、ActiveMQ的持久訊息儲存方案 前文已經講過,當ActiveMQ接收到PERSISTENT Message訊息後就需要藉助持久化方案來完成PERSISTENT Message的儲存。這個介質可以是磁碟檔案系統、可以是ActiveMQ的內建資料庫

架構設計系統通訊(37)——Apache Camel快速入門(中)

(補上文:Endpoint重要的漏講內容) 3-1-2、特殊的Endpoint Direct Endpoint Direct用於在兩個編排好的路由間實現Exchange訊息的連線,上一個路由中由最後一個元素處理完的Exchange物件,將被髮送至由D

架構設計系統通訊(28)——Kafka及場景應用(中1)

在本月初的寫作計劃中,我本來只打算粗略介紹一下Kafka(同樣是因為進度原因)。但是,最近有很多朋友要求我詳細講講Kafka的設計和使用,另外兩年前我在研究Kafka準備將其應用到生產環境時,由於沒有仔細理解Kafka的設計結構所導致的問題最後也還沒有進行交

架構設計系統通訊(26)——ActiveMQ叢集方案(下)

3、ActiveMQ熱備方案 ActiveMQ熱備方案,主要保證ActiveMQ的高可用性。這種方案並不像上節中我們主要討論的ActiveMQ高效能方案那樣,同時有多個節點都處於工作狀態,也就是說這種方案並不提高ActiveMQ叢集的效能;而是從叢集中的多

架構設計系統通訊(38)——Apache Camel快速入門(下1)

3-5-2-3迴圈動態路由 Dynamic Router 動態迴圈路由的特點是開發人員可以通過條件表示式等方式,動態決定下一個路由位置。在下一路由位置處理完成後Exchange將被重新返回到路由判斷點,並由動態迴圈路由再次做出新路徑的判斷。如此迴圈執行

架構設計系統通訊(2)——概述從“聊天”開始下篇

【轉】https://blog.csdn.net/yinwenjie/article/details/48344989 4-3、NIO通訊框架 目前流行的NIO框架非常的多。在論壇上、網際網路上大家討論和使用最多的有以下幾種: 原生JAVA NIO框架:

架構設計系統通訊——ActiveMQ叢集方案(上)

1、綜述 通過之前的文章,我們討論了ActiveMQ的基本使用,包括單個ActiveMQ服務節點的效能特徵,關鍵調整引數;我們還介紹了單個ActiveMQ節點上三種不同的持久化儲存方案,並討論了這三種不同的持久化儲存方案的配置和效能特點。但是這還遠遠不夠,因為在生產環境

每天3分鐘作業系統修煉祕籍(17)程序通訊(3)套接字

點我檢視祕籍連載 套接字 套接字(Socket)用於協調不同計算機上的程序間通訊,也就是基於網路的通訊。當然,也可以在本機上使用套接字進行程序間的通訊。 套接字通訊的方式非常多,有Unix域套接字、TCP套接字、UDP套接字、鏈路層套接字等等。但最常用的肯定是TCP套接字。所以,這裡介紹下TCP Socket

電子商城後臺系統(二)系統架構設計系統介紹

在寫一個程式之前,需要在大腦中對整個系統有一個初步的規劃,對於系統的功能模組,通常來說需要劃分成三大塊:框架部分、核心業務部分、擴充套件業務部分。 框架部分,通常是用來放通用的工具類方法,還有通用的處理資料、業務的方法,這些方法一般與系統的業務無關。電子商城的後臺系統,通常都會有許可權管理模組,