1 前言
- 不穩(wěn)定的網(wǎng)絡(luò)
- 有限的硬件資源
物聯(lián)網(wǎng)應(yīng)用兩大難題,MQTT 客戶端與服務(wù)器的連接可能隨時(shí)因網(wǎng)絡(luò)波動(dòng)及資源限制而異常斷開。為解決網(wǎng)絡(luò)連接斷開對通信造成的影響,MQTT 協(xié)議提供持久會話功能。
MQTT 客戶端在發(fā)起到服務(wù)器的連接時(shí),可設(shè)置是否創(chuàng)建一個(gè)持久會話。持久會話會保存一些重要數(shù)據(jù),以使會話能在多個(gè)網(wǎng)絡(luò)連接中繼續(xù)。
2 作用
- 避免因網(wǎng)絡(luò)中斷導(dǎo)致需要反復(fù)訂閱帶來的額外開銷
- 避免錯(cuò)過離線期間的消息
- 確保 QoS 1 和 QoS 2 的消息質(zhì)量保證不被網(wǎng)絡(luò)中斷影響
3 持久會話需存儲哪些數(shù)據(jù)?
通過上文我們知道持久會話需要存儲一些重要的數(shù)據(jù),以使會話能被恢復(fù)。這些數(shù)據(jù)有的存儲在客戶端,有的則存儲在服務(wù)端。
客戶端中存儲的會話數(shù)據(jù):
- 已發(fā)送給服務(wù)端,但是還沒有完成確認(rèn)的 QoS 1 與 QoS 2 消息
- 從服務(wù)端收到的,但是還沒有完成確認(rèn)的 QoS 2 消息
服務(wù)端中存儲的會話數(shù)據(jù):
- 會話是否存在,即使會話狀態(tài)其余部分為空。
- 已發(fā)送給客戶端,但是還沒有完成確認(rèn)的 QoS 1 與 QoS 2 消息。
- 等待傳輸給客戶端的 QoS 0 消息(可選),QoS 1 與 QoS 2 消息。
- 從客戶端收到的,但是還沒有完成確認(rèn)的 QoS 2 消息,遺囑消息和遺囑延時(shí)間隔。
4 MQTT Clean Session
控制會話狀態(tài)生命周期的標(biāo)志位:
-
true
表示創(chuàng)建一個(gè)新的會話,在客戶端斷開連接時(shí),會話將自動(dòng)銷毀 -
false
表示創(chuàng)建一個(gè)持久會話,在客戶端斷開連接后會話仍然保持,直到會話超時(shí)注銷
持久會話能被恢復(fù)的前提是客戶端使用固定 Client ID 再連,如 Client ID 動(dòng)態(tài),連接成功后將會創(chuàng)建一個(gè)新的持久會話。
如下Dashboard,圖中連接雖然是斷開狀態(tài),但因是持久會話,仍能被查看到,且可在 Dashboard 中手動(dòng)清除該會話:
EMQX 也支持在 Dashboard 設(shè)置 Session 相關(guān)參數(shù)。
MQTT 3.1.1 沒規(guī)定持久會話何時(shí)過期,僅從協(xié)議層理解,這持久會話應(yīng)永久存在。但實(shí)際場景不現(xiàn)實(shí),因?yàn)樗浅U挤?wù)端資源,所以服務(wù)端實(shí)際向用戶提供一個(gè)全局配置來限制會話過期時(shí)間。如設(shè)置會話過期時(shí)間 5 min,最大消息數(shù)為 1000 條,且不保存 QoS 0 消息。
5 使用
打開 MQTTX 后如下所示,點(diǎn)擊 New Connection
按鈕創(chuàng)建一個(gè) [MQTT 連接]。
創(chuàng)建名為 MQTT_V3
的連接,Clean Session 為關(guān)閉狀態(tài)(即為 false),MQTT 版本選擇 3.1.1,然后點(diǎn)擊右上角的 Connect
按鈕。
連接成功后訂閱 clean_session_false
主題,且 QoS 設(shè)置為 1。
訂閱成功后,點(diǎn)擊右上角的斷開連接按鈕。然后,創(chuàng)建一個(gè)名為 MQTT_V3_Publish
的連接,MQTT 版本同樣設(shè)置為 3.1.1,連接成功后向 clean_session_false
主題發(fā)布兩條 QoS 1 消息。
然后選中 MQTT_V3 連接,點(diǎn)擊連接按鈕連接至服務(wù)器,將會成功接收到兩條離線期間的消息。
6 MQTT 5.0 中的會話改進(jìn)
MQTT 5.0 中將 Clean Session 拆成:
-
Clean Start
指定連接時(shí)是創(chuàng)建一個(gè)全新的會話還是嘗試復(fù)用一個(gè)已存在的會話
-
Session Expiry Interval
指定網(wǎng)絡(luò)連接斷開后會話的過期時(shí)間
Clean Start 為 true
時(shí)表示必須丟棄任何已存在的會話,并創(chuàng)建一個(gè)全新的會話;為 false
時(shí)表示必須使用與 Client ID 關(guān)聯(lián)的會話來恢復(fù)與客戶端的通信(除非會話不存在)。
Session Expiry Interval 解決了 MQTT 3.1.1 中持久會話永久存在造成的服務(wù)器資源浪費(fèi)問題。設(shè)置為 0 或未設(shè)置,表示斷開連接時(shí)會話即到期;設(shè)置為大于 0 的數(shù)值,則表示會話在網(wǎng)絡(luò)連接關(guān)閉后會保持多少秒;設(shè)置為 0xFFFFFFFF
表示會話永遠(yuǎn)不會過期。
7 FAQ
當(dāng)會話結(jié)束后,保留消息還存在么?
[MQTT 保留消息]不是會話狀態(tài)的一部分,它們不會在會話結(jié)束時(shí)被刪除。
客戶端如何知道當(dāng)前會話是被恢復(fù)的會話?
MQTT 協(xié)議從 v3.1.1 開始,就為 CONNACK 報(bào)文設(shè)計(jì)了 Session Present 字段。當(dāng)服務(wù)器返回的該字段值為 1 時(shí),表示當(dāng)前連接將會復(fù)用服務(wù)器保存的會話??蛻舳丝赏ㄟ^該字段值決定在連接成功后是否需要重新訂閱。
使用持久會話的建議
- 不能使用動(dòng)態(tài) Client ID,需要保證客戶端每次連接的 Client ID 都是固定的。
- 根據(jù)服務(wù)器性能、網(wǎng)絡(luò)狀況、客戶端類型等合理評估會話過期時(shí)間。設(shè)置過長會占用更多的服務(wù)端資源,設(shè)置過短會導(dǎo)致未重連成功會話就失效。
- 當(dāng)客戶端確定不再需要會話時(shí),可使用 Clean Session 為 true 進(jìn)行重連,重連成功后再斷開連接。如果是 MQTT 5.0 則可在斷開連接時(shí)直接設(shè)置 Session Expiry Interval 為 0,表示連接斷開后會話即失效。
8 總結(jié)
至此完成對 MQTT 持久會話的介紹,并通過桌面客戶端演示了 Clean Session 的使用。讀者可參考本文借助 MQTT 持久會話實(shí)現(xiàn)離線消息的接收及降低訂閱開銷。
作者簡介:魔都國企技術(shù)專家,多家大廠后臺研發(fā)和架構(gòu)經(jīng)驗(yàn),負(fù)責(zé)復(fù)雜度極高業(yè)務(wù)系統(tǒng)的模塊化、服務(wù)化、平臺化研發(fā)工作。具有豐富帶團(tuán)隊(duì)經(jīng)驗(yàn),深厚人才識別和培養(yǎng)的積累。
參考:
編程嚴(yán)選網(wǎng)文章來源:http://www.zghlxwxcb.cn/news/detail-774302.html
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!文章來源地址http://www.zghlxwxcb.cn/news/detail-774302.html
到了這里,關(guān)于MQTT 持久會話 vs. Clean Session內(nèi)幕一網(wǎng)打盡的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!