Wolfram Hempel 是 deepstreamIO 的聯合創始人。deepstreamIO 是一家位於德國的技術創業公司,爲移動客戶端、及物聯網設備提供高性能、安全和可擴展的實時通訊服務。文本由魏佳翻譯,轉載譯文請註明來自高可用架構。html
想要向服務器發送請求並得到響應?直接使用 HTTP 吧!很是簡單。可是當須要經過持久的雙向鏈接來通訊時,如 WebSockets,固然你也有其它的選擇。
這篇文章會簡單扼要的解釋 MQTT,XMPP,STOMP,AMQP,WAMP 和其它替代品。這裏常被引用的 XKCD 漫畫[1]之一:java
確實如此,但這裏我將該術語(Realtime Protocol)看成一堆協議的代稱,這類協議都是設計用於分發消息,同步數據和經過持久雙向的鏈接來進行請求/響應。git
咱們先來根據它們各自的目的進行分類:github
底層協議(例如 TCP)是被設計用來將一個消息從一個發送者(sender)傳遞給一個接收者(receiver)。他們並不關係消息自己應該如何構建,也不關係消息的請求、獲取、存儲以及如何保證安全可靠。
像 WebSockets 這樣在 TCP 之上的協議,添加了一些額外的功能,例如使用頭部(header)傳輸元數據,經過多個數據包分割較大的消息,簡單的身份驗證,以及路由/重定向相關信息。本質上它們仍然是點對點交換數據的方式。
當涉及到構建更大,更復雜的系統時,你須要一個更高層次的通訊範式:apache
發佈-訂閱模式是在大規模系統中被普遍使用的通訊方式,用於多對多無狀態消息傳遞。「訂閱者」(Subscribers)能夠訂閱「消息主題」(topics,channels,events,namespaces), 「發佈者」(Publishers)能夠將消息發佈到「消息主題」,經過路由,全部的訂閱者都將收到。
這種範式是很是靈活,高效和可擴展。它將發送者與接收者隔離開,容許訂閱者自由得訂閱主題或取消訂閱。這和咱們平常訂閱報紙是同樣的。
有許多支持發佈-訂閱的協議:MQTT,STOMP,WAMP 等等。那麼咱們應該如何選擇呢?編程
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,Streaming Text Oriented Messaging Protocol)[7],是 WebSocket 通訊標準。在一般的發佈-訂閱語義之上,它經過 begin/publish/commit 序列以及 acknowledgement 機制來提供消息可靠投遞。
因爲協議簡單且易於實現,幾乎全部的編程語言都有 STOMP 的客戶端實現。可是在消息大小和處理速度方面並沒有優點。
當與 Apache Apollo[8] 這樣的多協議代理(multi-protocol broker)中間件結合使用時,能夠作許多有趣的集成。好比在瀏覽器的圖表中不斷更新 IoT 設備的數據。
到目前爲止,咱們已經講了兩個協議:一個二進制、另外一個基於文本。讓咱們快速比較一下差別:
經過控制線纜中光或電的打開或關閉(邏輯開關),或控制 WiFi 信號的波峯或波谷來實現計算機之間的信息交換。從原理上來講,這是基於二進制的形式。所以,從這個層面來講全部協議都是二進制協議。
信息一旦發送,接收方有兩個選擇:它能夠將 0/1 流分組成字節序列,進而獲取(解析)信息;或者能夠執行額外的步驟,將其轉換爲文本,而後再解析此文本。
前一種方法稱爲(基於)二進制的。它節省了一些昂貴的操做,同時是傳輸任何非文本信息的標準形式。
例如,圖像,音頻,視頻或文件。固然它也可用於發送文本信息。
例如,經過向每一個消息增長几個字節來表達元信息,好比描述該消息的長度或類型,這樣就只需將實際的消息數據轉換爲文本。
然而,因爲在許多發佈-訂閱式的架構中,信息交換是基於文本的,因此許多協議選擇簡單地將整個信息轉化爲文本,從而下降複雜性並提升了可讀性,固然帶來的代價就是須要再消息接受後執行額外的計算任務。
Web 應用消息協議(WAMP,Web Application Messaging Protocol)[9],它嘗試開發一種開放的、基於文本的協議標準,而且結合了基於發佈-訂閱的請求/響應編程模型,同時具有強大的路由和消息投遞策略。目前它被普遍用於集成 crossbar.io[10] 路由器和 autobahn 的高速緩存客戶端[11]。
那些實時通訊平臺即服務(Realtime platform-as-a-service)的產品,例如 Pusher 或 PubNub,一般使用它們本身的專有協議。Pusher 已經公開了它們研發的基於 JSON 協議的詳細規範[12],而且鼓勵第三方或社區幫助構建不一樣語言的客戶端。Pubnub 雖然更封閉一些,但它們目前支持一系列其它開放協議進行交互,如 MQTT。
有些場景下,簡單的發佈-訂閱模式還不夠。這就是隊列存在的場合:它支持多種不一樣的消息和存儲的模式。
經過獲取/確認策略,消費者接收到隊列的一些消息,確認他們的「消費」,處理它們,而後取下一批消息。這是一個強大同時經常使用的方式。
想象一下,你正在構建一個相似 Instagram 的產品,它容許用戶上傳圖片並添加各類濾鏡。應用濾鏡的過程是一個計算密集型的操做。所以,不能在上傳時直接進行操做,因此接收圖像的服務器只是記錄下在文件系統中的位置,接着將「什麼圖像須要使用什麼樣的濾鏡」這個任務添加到任務隊列中。
另外一臺專門用於處理濾鏡的機器能夠從任務隊列中獲取這個任務,讀取原始圖像文件,應用濾鏡,並確認這個任務已經消費(完成)。以後爲了水平擴展圖像處理的能力,只須要添加更多的消費者(處理濾鏡的機器)來處理任務隊列便可。
這種模式很是易於擴展,能夠添加複雜的路由策略,任務分配策略等。
高級消息隊列協議(AMQP,Advanced Message Queuing Protocol)[13]是各類消息隊列協議中的佼佼者。RabbitMQ[14] 和 HornetQ[15] 都是實現該協議的流行中間件。
當簡單的發佈-訂閱模型不能知足使用要求。AMQP 十分可靠且功能強大。固然它及它的實現並非足夠輕量級。若是你須要一個更輕量級的選擇,那接下來的內容可能會更好:
ZeroMQ[16] 既是一個協議,也是一套協議實現的組件。提供比 AMQP 更高速同時去中心化的替代方案。
當你須要海量吞吐以及無單點故障風險的消息隊列支撐你的複雜工做流,那麼 ZeroMQ 是個不錯的選擇,固然,你須要對陡峭的學習曲線作好準備。
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。
DataSync 是實現實時通訊的最新可選方案。
DataSync 將數據存儲中的數據同步給客戶端。客戶端對數據的變動都將同步給全部的訂閱者。DataSync 隱藏了實時通訊類應用中維護數據狀態的細節,下降了複雜性,並極大加快了開發速度,但它目前仍然是一種沒有開放的協議標準。
目前 DataSync 已能夠在幾個 PaaS 平臺上使用,如 deepstreamHub[18],Firebase[19] 或 Realm[20]。
利用 deepstream[21] 的分佈式實時協議(DRP,Distributed Realtime Protocol),咱們有信心找到一種方法,將全部上述概念組合成一個協議,同時確保消息大小,可擴展性和互操做性方面的效率最大化。
https://xkcd.com/
http://mqtt.org/
https://mosquitto.org/
https://vernemq.com/
http://www.hivemq.com/
https://www.cloudmqtt.com/
https://stomp.github.io/
https://activemq.apache.org/apollo/
http://wamp-proto.org/
http://crossbar.io/
http://crossbar.io/autobahn/
https://pusher.com/docs/pusher_protocol
https://www.amqp.org/
https://www.rabbitmq.com/
http://hornetq.jboss.org/
http://zeromq.org/
http://docs.oracle.com/javaee/6/tutorial/doc/bncdq.html
https://deepstreamhub.com/
https://firebase.google.com/
https://realm.io/
https://deepstream.io/
推薦閱讀
https://mp.weixin.qq.com/s/IyvKMTQY3Nzt719Bs09uyg