在機智云的整個架構里面,如上圖,GAgent實現了從模塊到云端的數據交互,其實GAgent里面就是用MQTT協議實現的,可見MQTT協議的重要性。今天介紹MQTT的發布、訂閱和取消訂閱。 回顧
在上一篇文章中,我們解釋了發布/訂閱模式是如何工作的以及如何在MQTT中應用,以下我們把要點回顧下:發布或者訂閱解耦一個客戶端,就是從另一個客戶端(或更多客戶端)發送特定消息(稱為發布者),為了確定哪個消息發送到哪個客戶端,MQTT使用了主題。主題是層次結構的字符串,用于消息過濾和路由。
在上一章節的最后我又更具理論性的分析了,發布/訂閱是什么,以及如何從消息排隊方法中區分MQTT。這篇文章干貨將更多,主要介紹MQTT的基本知識。這一章,我們討論的主題是MQTT客戶端和代理服務器的定義以及MQTT連接的基礎知識,如何連接、連接需要的參數。 引言
我們已經看看完了MQTT的發布和訂閱后,所有的設備都要和代理服務器連接的,我們在講連接之前應該理解下客戶端和代理服務器。 客戶端
在文章中,我們討論的客戶端都是MQTT客戶端,說的發布者和訂閱者也都指的是MQTT客戶端的發布和訂閱(通常,MQTT客戶端可以同時發布和訂閱)MQTT客戶端是從微控制器到完整的服務器的任何設備,它具有運行的MQTT庫,并通過任何類型的網絡連接到MQTT代理。這是一個非常小且資源有限的設備它通過無線網絡連接,并且設定一定參數,或者運行圖形化MQTT客戶端的典型計算機用于測試目的,總的來說基本上是具有TCP / IP協議棧并在其上支持MQTT協議的任何設備。
MQTT協議的客戶端實現非常直觀,簡單,有人會問了,為什么MQTT非常適合小型設備呢?MQTT客戶端庫可用于各種各樣的編程語言,如Android, Arduino, C, C++, C#, Go, iOS, Java, JavaScript, .NET. 可以在維基百科上找到MQTT的完整的列表。 代理
MQTT客戶端的對應方就是MQTT代理服務器,這是任何發布和訂閱協議的核心,根據具體實現情況,代理可以處理多達數千個并發連接的MQTT客戶端。代理主要負責接收所有消息,過濾它們,決定誰對其感興趣,然后將消息發送給相應訂閱客戶端。它還擁有所有持久客戶端的會話,包括訂閱和錯過的消息。
代理的另一責任是給客戶端認證和授權,而且在大多數時候,代理也是可擴展的,這樣可以輕松地自定義身份驗證,授權并且集成到后端系統中。集成是一個重要的方面,因為代理通常是直接暴露在互聯網上并處理大量客戶端的組件,然后將消息傳遞到下游分析和處理系統。
正如我們在我們早期博客中所描述的一樣,訂閱所有消息并不是一個真正的選擇,所有的代理都是中心樞紐,每個消息都需要通過它的。因此,重要的是,它具有高度可擴展性,可集成到后端系統中,這樣易于監控,當然也具有抗故障性,才能保障穩定。例如,HiveMQ通過使用最先進的事件驅動網絡處理,一個開放的插件系統和標準的監控為用戶提供服務。 MQTT連接
MQTT協議基于TCP / IP的,客戶端和代理都需要具有TCP / IP協議棧。
33.jpg (12.19 KB, 下載次數: 103)
下載附件
2017-8-25 08:56 上傳
MQTT連接本身始終在一個客戶端和代理之間,沒有客戶端直接連接到另一個客戶端。通過客戶端向代理發送CONNECT消息來啟動連接。具有CONNACK的代理響應并發送狀態代碼。建立連接后,只要客戶端沒有發送斷開連接命令或者斷開連接網絡,代理將一直保持打開狀態。
44.jpg (15.9 KB, 下載次數: 98)
下載附件
2017-8-25 08:57 上傳
MQTT通過NAT連接 MQTT客戶端一般是連接路由器設備的,它們正在使用網絡地址轉換(NAT),以便從專用網絡地址(如192.168.x.x,10.0.x.x)轉換為面向公眾的公共網絡。如前所述,MQTT客戶端第一步就要要發送CONNECT消息。因此,NAT后面的客戶端沒有任何問題,因為代理具有公共地址,并且連接將保持打開,以允許在初始CONNECT之后雙向發送和接收消息。
下面讓我們看看MQTT客戶端發送的連接信息。前面已經提到,這是從客戶端到代理發起連接。如果CONNECT消息格式錯誤(根據MQTT規范)或打開網路超時,代理將關閉連接。這是合理的行為,這樣可以避免惡意客戶端攻擊,減慢代理的速度。 一個完好的客戶端將發送一個包含以下內容的連接消息:
55.jpg (23.13 KB, 下載次數: 70)
下載附件
2017-8-25 08:57 上傳
此外,CONNECT消息中還包含其他信息,這對MQTT庫的編寫者而言比對庫的使用者更加關心。如果您對詳細信息有興趣,請查看MQTT 3.1.1規范。 下面讓我們逐個瀏覽所有這些項目參數吧: 客戶端標識符(簡稱ClientId)是連接到MQTT代理的每個MQTT客戶端的標識符。正如標識符的含義那樣,每個代理應該是唯一的。代理使用它來識別客戶端和客戶端的當前狀態。如果不需要一個狀態來保持代理,在MQTT 3.1.1(當前標準)中,也可以發送一個空的ClientId。這導致沒有任何狀態的連接,條件是 Clean Session是真的,否則連接將被拒絕。 Clean Session標志指示代理,客戶端是否要建立持久會話。持久會話(CleanSession為假)表示代理將存儲客戶端的所有訂閱以及所有錯過的信息。當使用服務質量(QoS)1或2進行訂閱時。如果Clean Session設置為真,則代理不會為客戶端存儲任何東西,并且還將清除以前持續會話中的所有信息。 MQTT允許發送用于驗證客戶端的用戶名和密碼以及授權。然而,密碼是以明文形式發送的,如果它沒有通過實現加密或散列,或者使用TLS。我們強烈建議使用用戶名和密碼以及安全的傳輸,在像HiveMQ這樣的代理中,也可以使用SSL證書對客戶端進行身份驗證,因此不需要用戶名和密碼。 Will Message是MQTT的最后一個意愿和遺囑特征的一部分。它允許通知其他客戶端,當客戶端不正常地斷開連接。連接客戶端將在CONNECT消息中以MQTT消息和主題的形式提供他的意愿。如果客戶端不正常地斷開連接,代理客戶端會發送此消息。我們會在后面的文章中單獨介紹一下。 KeepAlive是一個時間間隔,客戶端通過向代理發送常規PING請求消息。代理將與PING響應,這種機制將確定雙方是否仍然存在和正常通信。這個我們將在以后的一篇文章中詳細介紹一下。這基本上都是從MQTT客戶端連接到MQTT代理所需的所有信息。每個MQTT庫通常都會有其他選項,可以進行具體配置。 當代理獲得CONNECT消息時,代理有義務使用CONNACK消息進行響應。CONNACK只包含兩個數據條目:會話存在標志,連接確認標志。 會話存在標志指示,代理是否已經具有來自先前交互的客戶端的持久會話。如果客戶端連接并將CleanSession設置為真,則此標志始終為假,因為沒有會話可用。如果客戶端將CleanSession設置為假,則該標志取決于該ClientId是否存在可用于的會話信息。如果存儲會話信息,則該標志為真,否則為假。該標志在MQTT 3.1.1中新添加,并幫助客戶端確定是否必須訂閱主題,或者是否仍然存儲在他的會話中。 CONNACK中的第二個標志是連接確認標志。它指示客戶端,是否連接成功和沒有連接成功的原因是什么。
在下表中,您可以一目了然地看到所有的返回代碼。
66.jpg (14.1 KB, 下載次數: 98)
下載附件
2017-8-25 08:57 上傳
這些更詳細的說明可以在MQTT規范中找到 問題
您可能會問,即使沒有發送消息,MQTT如何保持連接的打開狀態?或者如何知道連接何時丟失?你必須耐心等待,但是我們將在后面的整個博客里面寫下一些關于這個主題的必要內容。
77.jpg (16.33 KB, 下載次數: 81)
下載附件
2017-8-25 08:57 上傳
這就是我們的MQTT 要點系列的第三部分的結尾。我們希望您能了解至少一件關于MQTT的基本知識,并期待下一篇關于如何在MQTT中發布,訂閱和取消訂閱的文章。 學習總結
都是很重點的內容,可以先看看這個文檔再去看官方協議,畢竟這個要比官方協議講的要通俗易懂些,很有收獲的。
|