1. 程式人生 > >訊息協議(MQTT、AMQP、XMPP、WAMP、STOMP)之間的區別和應用

訊息協議(MQTT、AMQP、XMPP、WAMP、STOMP)之間的區別和應用

這篇文章會簡單扼要的解釋 MQTT,XMPP,STOMP,AMQP,WAMP 等。我們先來根據它們各自的目的進行分類:

 

1、純訊息

底層協議(例如 TCP)是被設計用來將一個訊息從一個傳送者(sender)傳遞給一個接收者(receiver)。他們並不關係訊息本身應該如何構建,也不關係訊息的請求、獲取、儲存以及如何保證安全可靠。

像 WebSockets 這樣在 TCP 之上的協議,添加了一些額外的功能,例如使用頭部(header)傳輸元資料,通過多個數據包分割較大的訊息,簡單的身份驗證,以及路由/重定向相關資訊。本質上它們仍然是點對點交換資料的方式。

當涉及到構建更大,更復雜的系統時,你需要一個更高層次的通訊正規化:

2、釋出-訂閱

釋出-訂閱模式是在大規模系統中被廣泛使用的通訊方式,用於多對多無狀態訊息傳遞。“訂閱者”(Subscribers)可以訂閱“訊息主題”(topics,channels,events,namespaces), “釋出者”(Publishers)可以將訊息釋出到“訊息主題”,通過路由,所有的訂閱者都將收到。

這種正規化是非常靈活,高效和可擴充套件。它將傳送者與接收者隔離開,允許訂閱者自由得訂閱主題或取消訂閱。這和我們日常訂閱報紙是一樣的。

有許多支援釋出-訂閱的協議:MQTT,STOMP,WAMP 等等。那麼我們應該如何選擇呢?

 

MQTT

MQTT(Message Queue Telemerty Transport)[2]是一種二進位制協議,主要用於伺服器和那些低功耗的物聯網裝置(IoT)之間的通訊。

它位於 TCP 協議的上層,除了提供釋出-訂閱這一基本功能外,也提供一些其它特性:不同的訊息投遞保障(delivery guarantee),“至少一次”和“最多一次”。通過儲存最後一個被確認接受的訊息來實現重連後的訊息恢復。


它非常輕量級,並且從設計和實現層面都適合用於不穩定的網路環境中。

 

什麼時候應使用它?

 

物聯網(IoT)場景中更適合,支援幾乎所有語言進行開發,並且瀏覽器也可通過 WebSocket 來發送和接收 MQTT 訊息。
 

同時,對於MQTT Broker,也有很多選擇,如 Mosquitto[3] 或 VerneMQ[4] 以及基於雲的 MQTT 平臺,如 HiveMQ[5] 或 CloudMQTT[6]。

 

STOMP

面向流文字的訊息傳輸協議(STOMP,Streaming Text Oriented Messaging Protocol)[7],是 WebSocket 通訊標準。在通常的釋出-訂閱語義之上,它通過 begin/publish/commit 序列以及 acknowledgement 機制來提供訊息可靠投遞。
 

由於協議簡單且易於實現,幾乎所有的程式語言都有 STOMP 的客戶端實現。但是在訊息大小和處理速度方面並無優勢。

 

什麼時候會使用它?

當與 Apache Apollo[8] 這樣的多協議代理(multi-protocol broker)中介軟體結合使用時,可以做許多有趣的整合。比如在瀏覽器的圖表中不斷更新 IoT 裝置的資料。

 

 

選擇二進位制還是基於文字?

到目前為止,我們已經講了兩個協議:一個二進位制、另一個基於文字。讓我們快速比較一下差異:

通過控制線纜中光或電的開啟或關閉(邏輯開關),或控制 WiFi 訊號的波峰或波谷來實現計算機之間的資訊交換。從原理上來說,這是基於二進位制的形式。因此,從這個層面來說所有協議都是二進位制協議。

資訊一旦傳送,接收方有兩個選擇:它可以將 0/1 流分組成位元組序列,進而獲取(解析)資訊;或者可以執行額外的步驟,將其轉換為文字,然後再解析此文字。

前一種方法稱為(基於)二進位制的。它節省了一些昂貴的操作,同時是傳輸任何非文字資訊的標準形式。例如,影象,音訊,視訊或檔案。當然它也可用於傳送文字資訊。例如,通過向每個訊息增加幾個位元組來表達元資訊,比如描述該訊息的長度或型別,這樣就只需將實際的訊息資料轉換為文字。

然而,由於在許多釋出-訂閱式的架構中,資訊交換是基於文字的,所以許多協議選擇簡單地將整個資訊轉化為文字,從而降低複雜性並提高了可讀性,當然帶來的代價就是需要再訊息接受後執行額外的計算任務。

 

 

WAMP

Web 應用訊息協議(WAMP,Web Application Messaging Protocol)[9],它嘗試開發一種開放的、基於文字的協議標準,並且結合了基於釋出-訂閱的請求/響應程式設計模型,同時具備強大的路由和訊息投遞策略。目前它被廣泛用於整合 crossbar.io[10] 路由器和 autobahn 的快取記憶體客戶端[11]。

 

Pusher / PubNub&Co

那些實時通訊平臺即服務(Realtime platform-as-a-service)的產品,例如 Pusher 或 PubNub,通常使用它們自己的專有協議。Pusher 已經公開了它們研發的基於 JSON 協議的詳細規範[12],並且鼓勵第三方或社群幫助構建不同語言的客戶端。Pubnub 雖然更封閉一些,但它們目前支援一系列其它開放協議進行互動,如 MQTT。

 

3、佇列

有些場景下,簡單的釋出-訂閱模式還不夠。這就是佇列存在的場合:它支援多種不同的訊息和儲存的模式。
 

通過獲取/確認策略,消費者接收到佇列的一些訊息,確認他們的“消費”,處理它們,然後取下一批訊息。這是一個強大同時常用的方式。
 

想象一下,你正在構建一個類似 Instagram 的產品,它允許使用者上傳圖片並新增各種濾鏡。應用濾鏡的過程是一個計算密集型的操作。因此,不能在上傳時直接進行操作,所以接收影象的伺服器只是記錄下在檔案系統中的位置,接著將“什麼影象需要使用什麼樣的濾鏡”這個任務新增到任務佇列中。
 

另一臺專門用於處理濾鏡的機器可以從任務佇列中獲取這個任務,讀取原始影象檔案,應用濾鏡,並確認這個任務已經消費(完成)。之後為了水平擴充套件影象處理的能力,只需要新增更多的消費者(處理濾鏡的機器)來處理任務佇列即可。
 

這種模式非常易於擴充套件,可以新增複雜的路由策略,任務分配策略等。

AMQP

高階訊息佇列協議(AMQP,Advanced Message Queuing Protocol)[13]是各種訊息佇列協議中的佼佼者。RabbitMQ[14] 和 HornetQ[15] 都是實現該協議的流行中介軟體。

 

什麼時候會使用它?

當簡單的釋出-訂閱模型不能滿足使用要求。AMQP 十分可靠且功能強大。當然它及它的實現並不是足夠輕量級。如果你需要一個更輕量級的選擇,那接下來的內容可能會更好:

ZeroMQ

ZeroMQ[16] 既是一個協議,也是一套協議實現的元件。提供比 AMQP 更高速同時去中心化的替代方案。

 

什麼時候會使用它?

當你需要海量吞吐以及無單點故障風險的訊息佇列支撐你的複雜工作流,那麼 ZeroMQ 是個不錯的選擇,當然,你需要對陡峭的學習曲線做好準備。

JMS

Java 訊息服務(JMS,Java Messaging Service)[17],是協議同時也是 Java 訊息服務規範的標準實現,同時也是 Java 企業版(JEE)規範的一部分。

 

什麼時候應使用它?

當你使用 Java 棧,同時也為 Java Enterprise Platform 付費了,那 JMS 是最佳選擇。如果沒有,那就優先考慮上述那些方案。
 

請求/響應

有時我們只需要傳送單個請求,並等待收到一個響應,這完全可以使用HTTP請求完成 / 。 但是既然你已經建立了一個與伺服器的持久連線 ,那為什麼不利用它呢?

這種通過持久連線進行的請求/響應模式的通訊過程,通常被稱為遠端過程呼叫(RPC,Remote Procedure Calls)或遠端方法呼叫(RMI,Remote Method Invocation)。AMQP 或 ZeroMQ 可以通過響應佇列(response-queue)來實現這種模式,JMS 可以直接支援 Java RMI。

 

4、DataSync

DataSync 是實現實時通訊的最新可選方案。

DataSync 將資料儲存中的資料同步給客戶端。客戶端對資料的變更都將同步給所有的訂閱者。DataSync 隱藏了實時通訊類應用中維護資料狀態的細節,降低了複雜性,並極大加快了開發速度,但它目前仍然是一種沒有開放的協議標準。

目前 DataSync 已可以在幾個 PaaS 平臺上使用,如 deepstreamHub[18],Firebase[19] 或 Realm[20]