什么是MQTT
MQTT 是一種基于發(fā)布/訂閱模式的輕量級消息傳輸協(xié)議,專門針對低帶寬和不穩(wěn)定網(wǎng)絡(luò)環(huán)境的物聯(lián)網(wǎng)應(yīng)用 而設(shè)計(jì),可以用極少的代碼為聯(lián)網(wǎng)設(shè)備提供實(shí)時可靠的消息服務(wù)。MQTT 協(xié)議廣泛應(yīng)用于物聯(lián)網(wǎng)、移動互 聯(lián)網(wǎng)、智能硬件、車聯(lián)網(wǎng)、智慧城市、遠(yuǎn)程醫(yī)療、電力、石油與能源等領(lǐng)域。
MQTT特點(diǎn)
1. 簡單容易實(shí)現(xiàn)
2. 支持 QoS(設(shè)備網(wǎng)絡(luò)環(huán)境復(fù)雜)
3. 輕量且省帶寬(因?yàn)槟菚r候帶寬很貴)
4. 數(shù)據(jù)無關(guān)(不關(guān)心 Payload 數(shù)據(jù)格式)
5. 有持續(xù)地會話感知能力(時刻知道設(shè)備是否在線)
為什么 MQTT 是適用于物聯(lián)網(wǎng)
據(jù) IoT Analytics 最新發(fā)布的《2022 年春季物聯(lián)網(wǎng)狀況》研究報告顯示,到 2022 年,物聯(lián)網(wǎng)市場預(yù)計(jì) 將增長 18%,達(dá)到 144 億活躍連接。在如此大規(guī)模的物聯(lián)網(wǎng)需求下,海量的設(shè)備接入和設(shè)備管理對網(wǎng)絡(luò)帶寬、通信協(xié)議以及平臺服務(wù)架構(gòu)都帶 來了巨大的挑戰(zhàn)。對于物聯(lián)網(wǎng)協(xié)議來說,必須針對性地解決物聯(lián)網(wǎng)設(shè)備通信的幾個關(guān)鍵問題:網(wǎng)絡(luò)環(huán)境復(fù) 雜而不可靠、內(nèi)存和閃存容量小、處理器能力有限。MQTT 協(xié)議正是為了應(yīng)對以上問題而創(chuàng)建,經(jīng)過多年的發(fā)展憑借其輕量高效、可靠的消息傳遞、海量連接 支持、安全的雙向通信等優(yōu)點(diǎn)已成為物聯(lián)網(wǎng)行業(yè)的首選協(xié)議 。
基本概念
完整的MQTT交互由MQTT服務(wù)器、MQTT客戶端組成。
MQTT服務(wù)器
MQTT 服務(wù)器負(fù)責(zé)接收客戶端發(fā)起的連接,并將客戶端發(fā)送的消息轉(zhuǎn)發(fā)到另外一些符合條件的客戶端。一 個成熟的 MQTT 服務(wù)器可支持海量的客戶端連接及百萬級的消息吞吐,幫助物聯(lián)網(wǎng)業(yè)務(wù)提供商專注于業(yè)務(wù) 功能并快速創(chuàng)建一個可靠的 MQTT 應(yīng)用。
MQTT客戶端
MQTT 應(yīng)用通常需要基于 MQTT 客戶端庫來實(shí)現(xiàn) MQTT 通信。目前,基本所有的編程語言都有成熟的開源MQTT 客戶端庫??梢酝ㄟ^編程的方式使得各類應(yīng)用作為MQTT客戶端。
MQTT 發(fā)布/訂閱模式介紹
發(fā)布訂閱模式(Publish-Subscribe Pattern)是一種消息傳遞模式,它將發(fā)送消息的客戶端(發(fā)布者)與 接收消息的客戶端(訂閱者)解耦,使得兩者不需要建立直接的聯(lián)系也不需要知道對方的存在。
MQTT 發(fā)布/訂閱模式的精髓在于由一個被稱為代理(Broker)的中間角色負(fù)責(zé)所有消息的路由和分發(fā)工 作,發(fā)布者將帶有主題的消息發(fā)送給代理,訂閱者則向代理訂閱主題來接收感興趣的消息。
MQTT 發(fā)布/訂閱模式有 4 個主要組成部分:發(fā)布者、訂閱者、代理和主題。
發(fā)布者(Publisher)
負(fù)責(zé)將消息發(fā)布到主題上,發(fā)布者一次只能向一個主題發(fā)送數(shù)據(jù),發(fā)布者發(fā)布消息時也無需關(guān)心訂閱 者是否在線。
訂閱者(Subscriber)
訂閱者通過訂閱主題接收消息,且可一次訂閱多個主題。MQTT 還支持通過共享訂閱的方式在多個訂 閱者之間實(shí)現(xiàn)訂閱的負(fù)載均衡。
代理(Broker)
負(fù)責(zé)接收發(fā)布者的消息,并將消息轉(zhuǎn)發(fā)至符合條件的訂閱者。另外,代理也需要負(fù)責(zé)處理客戶端發(fā)起 的連接、斷開連接、訂閱、取消訂閱等請求。
主題(Topic)
主題是 MQTT 進(jìn)行消息路由的基礎(chǔ),它類似 URL 路徑,使用斜杠 / 進(jìn)行分層,比如 sensor/1/temperature。一個主題可以有多個訂閱者,代理會將該主題下的消息轉(zhuǎn)發(fā)給所有訂閱者;一個 主題也可以有多個發(fā)布者,代理將按照消息到達(dá)的順序轉(zhuǎn)發(fā)。
創(chuàng)建MQTT連接
建立一個 MQTT 連接是使用 MQTT 協(xié)議進(jìn)行通信的第一步。為了保證高可擴(kuò)展性,在建立連接時 MQTT 協(xié)議提供了豐富的連接參數(shù),以方便開發(fā)者能創(chuàng)建滿足不同業(yè)務(wù)需求的物聯(lián)網(wǎng)應(yīng)用。
本文采用TCP/IP連接方式演示。
連接參數(shù)
連接地址
MQTT 的連接地址通常包含 :服務(wù)器 IP 或者域名、服務(wù)器端口、連接協(xié)議?;?TCP 的 MQTT 連接 mqtt 是普通的 TCP 連接,端口一般為 1883。mqtts 是基于 TLS/SSL 的安全連接,端口一般為 8883。比如 mqtt://broker.emqx.io:1883 是一個基于普通 TCP 的 MQTT 連接地址。
客戶端 ID(Client ID)
MQTT 服務(wù)器使用 Client ID 識別客戶端,連接到服務(wù)器的每個客戶端都必須要有唯一的 Client ID。Client ID 的長度通常為 1 至 23 個字節(jié)的 UTF-8 字符串。如果客戶端使用一個重復(fù)的 Client ID 連接至服務(wù)器,將會把已使用該 Client ID 連接成功的客戶端踢下 線。
用戶名與密碼(Username & Password)
MQTT 協(xié)議可以通過用戶名和密碼來進(jìn)行相關(guān)的認(rèn)證和授權(quán),但是如果此信息未加密,則用戶名和密碼將 以明文方式傳輸。如果設(shè)置了用戶名與密碼認(rèn)證,那么最好要使用 mqtts 或 wss 協(xié)議。大多數(shù) MQTT 服務(wù)器默認(rèn)為匿名認(rèn)證,匿名認(rèn)證時用戶名與密碼設(shè)置為空字符串即可。
連接超時(Connect Timeout)
連接超時時長,收到服務(wù)器連接確認(rèn)前的等待時間,等待時間內(nèi)未收到連接確認(rèn)則為連接失敗。
?;钪芷?Keep Alive)
?;钪芷?,是一個以秒為單位的時間間隔??蛻舳嗽跓o報文發(fā)送時,將按 Keep Alive 設(shè)定的值定時向服務(wù) 端發(fā)送心跳報文,確保連接不被服務(wù)端斷開。在連接建立成功后,如果服務(wù)器沒有在 Keep Alive 的 1.5 倍時間內(nèi)收到來自客戶端的任何包,則會認(rèn)為 和客戶端之間的連接出現(xiàn)了問題,此時服務(wù)器便會斷開和客戶端的連接。
清除會話(Clean Session)
為 false 時表示創(chuàng)建一個持久會話,在客戶端斷開連接時,會話仍然保持并保存離線消息,直到會話超時 注銷。為 true 時表示創(chuàng)建一個新的臨時會話,在客戶端斷開時,會話自動銷毀。持久會話避免了客戶端掉線重連后消息的丟失,并且免去了客戶端連接后重復(fù)的訂閱開銷。這一功能在帶 寬小,網(wǎng)絡(luò)不穩(wěn)定的物聯(lián)網(wǎng)場景中非常實(shí)用。注意:持久會話恢復(fù)的前提是客戶端使用固定的 Client ID 再次連接,如果 Client ID 是動態(tài)的, 那么連接成功后將會創(chuàng)建一個新的持久會話。服務(wù)器為持久會話保存的消息數(shù)量取決于服務(wù)器的配置,比如 EMQ 提供的免費(fèi)的公共 MQTT 服務(wù)器設(shè) 置的離線消息保存時間為 5 分鐘,最大消息數(shù)為 1000 條,且不保存 QoS 0 消息。
遺囑消息(Last Will)
遺囑消息是 MQTT 為那些可能出現(xiàn)意外斷線的設(shè)備提供的將遺囑優(yōu)雅地發(fā)送給其他客戶端的能力。設(shè)置了 遺囑消息消息的 MQTT 客戶端異常下線時,MQTT 服務(wù)器會發(fā)布該客戶端設(shè)置的遺囑消息。意外斷線包括:因網(wǎng)絡(luò)故障,連接被服務(wù)端關(guān)閉;設(shè)備意外掉電;設(shè)備嘗試進(jìn)行不被允許的操作而被 服務(wù)端關(guān)閉連接等。遺囑消息可以看作是一個簡化版的 MQTT 消息,它也包含 Topic、Payload、QoS、Retain 等信息。
· 當(dāng)設(shè)備意外斷線時,遺囑消息將被發(fā)送至遺囑 Topic;
· 遺囑 Payload 是待發(fā)送的消息內(nèi)容;
· 遺囑 QoS 與普通 MQTT 消息的 QoS 一致 ;
· 遺囑 Retain 為 true 時表明遺囑消息是保留消息。MQTT 服務(wù)器會為每個主題存儲最新一條保留消 息,以方便消息發(fā)布后才上線的客戶端在訂閱主題時仍可以接收到該消息。
MQTT 5.0
隨著物聯(lián)網(wǎng)行業(yè)的發(fā)展,應(yīng)用的需求也在不斷變化。為了適應(yīng)這些新的需求,在 2019 年發(fā)布了 MQTT 5.0,其中加入了一些新功能。MQTT 5.0 也因此能夠更好地滿足現(xiàn)代物聯(lián)網(wǎng)應(yīng)用的復(fù)雜需求。
MQTT 5.0 的 7 個新功能
1. 原因代碼:了解斷開連接或失敗原因
MQTT5.0能夠?yàn)槊總€確認(rèn)報文提供一個原因代碼,幫助我們了解斷開連接或發(fā)生故障的原因??梢酝ㄟ^ (http://985.so/kahfq)來迅速定位問題。
2. 會話過期間隔:管理會話的生命周期
這個功能允許客戶端指定服務(wù)器在客戶端斷開連接后應(yīng)將會話保持多長時間。在之前的 MQTT 版本中,會話要么在斷開連接后立即結(jié)束,要么無限期地保持下去。使用 MQTT 5.0,您可以指定一個具體的時間段,在斷開連接后,會話仍然有效。這樣可以更靈活地管理會話的生命周期,并節(jié)省服務(wù)器的資源。
3. 主題別名:減少消息頭部的開銷
MQTT 5.0 引入了主題別名,以減少消息頭部的開銷。在之前的版本中,每個消息都需要包含主題名稱,導(dǎo)致數(shù)據(jù)包過大。
使用主題別名,可以為主題分配一個簡短的數(shù)字別名。這個別名可以在后續(xù)的消息中替代完整的主題名稱,大大減少了 MQTT 頭部的大小,從而節(jié)省了網(wǎng)絡(luò)帶寬。
4. 用戶屬性:MQTT 頭部中的自定義元數(shù)據(jù)
這個功能讓用戶可以在 MQTT 報文的頭部添加自定義的元數(shù)據(jù)。這對于需要在 MQTT 消息中攜帶額外信息的應(yīng)用非常有用,比如消息的時間戳、設(shè)備位置或其他應(yīng)用相關(guān)的數(shù)據(jù)。用戶屬性增加了 MQTT 消息傳輸?shù)撵`活性和控制力。
5. 訂閱選項(xiàng):細(xì)粒度的訂閱控制
MQTT 5.0 讓客戶端可以指定如何接收每個訂閱主題的消息。比如,客戶端可以指定他們是否接收某個訂閱的保留消息,或者是否接收和訂閱具有相同 QoS(服務(wù)質(zhì)量)級別的消息。
6. 請求/響應(yīng):允許客戶端回復(fù)指定主題
請求/響應(yīng)功能讓客戶端可以指定一個主題,供服務(wù)器直接回復(fù)。
在早期的 MQTT 版本中,如果客戶端想要回復(fù)一條消息,它必須把回復(fù)發(fā)布到一個主題,而原始發(fā)送者必須訂閱那個主題才能收到回復(fù)。使用 MQTT 5.0 的請求/響應(yīng)功能,客戶端和服務(wù)器之間的通信變得更高效和簡潔。
7. 共享訂閱:訂閱者負(fù)載均衡功能
這個功能讓多個客戶端可以共享一個訂閱。當(dāng)一條消息發(fā)布到一個共享主題時,服務(wù)器會把消息分發(fā)給共享訂閱中的某個客戶端,從而實(shí)現(xiàn)消息的負(fù)載均衡。
這個功能在有多個服務(wù)實(shí)例運(yùn)行,并且想要平均分配工作量的場景中非常有用。