MQTT 協議中的 Keep Alive 機制
為什么需要 Keep Alive
MQTT 協議是承載於 TCP 協議之上的,而 TCP 協議以連接為導向,在連接雙方之間,提供穩定、有序的字節流功能。 但是,在部分情況下,TCP 可能出現半連接問題。所謂半連接,是指某一方的連接已經斷開或者沒有建立,而另外一方的連接卻依然維持着。在這種情況下,半連接的一方可能會持續不斷地向對端發送數據,而顯然這些數據永遠到達不了對端。為了避免半連接導致的通信黑洞,MQTT 協議提供了 Keep Alive 機制,使客戶端和 MQTT 服務器可以判定當前是否存在半連接問題,從而關閉對應連接。
Keep Alive 的機制流程與使用
啟用
客戶端在創建和 MQTT Broker 的連接時,只要將連接請求協議包內的 Keep Alive 可變頭部字段設置為非 0 值,就可以在通信雙方間啟用 Keep Alive 機制。 Keep Alive 為 0~65535 的一個整數,代表客戶端發送兩次 MQTT 協議包之間的最大間隔時間。
而 Broker 在收到客戶端的連接請求后,會檢查可變頭部中的 Keep Alive 字段的值,如果有值,則 Broker 將會啟用 Keep Alive 機制。
在 MQTT 5.0 標准中,引入了 Server Keep Alive 的概念,允許 Broker 根據自身的實現等因素,選擇接受客戶端請求中攜帶的 Keep Alive 值,或者是覆蓋這個值。如果 Broker 選擇覆蓋這個值,則需要將新值設置在連接確認包(CONNACK) 的 Server Keep Alive 字段中,客戶端如果在連接確認包中讀取到了 Server Keep Alive,則需要使用該值,覆蓋自己之前的 Keep Alive 的值。
Keep Alive 機制流程
-
客戶端流程
在連接建立后,客戶端需要確保, 自己任意兩次 MQTT 協議包的發送間隔不超過 Keep Alive 的值,如果客戶端當前處於空閑狀態,沒有可發送的包,則可以發送 PINGREQ 協議包。
當客戶端發送 PINGREQ 協議包后,Broker 必須返回一個 PINGRESP 協議包,如果客戶端在一個可靠 的時間內,沒有收到服務器的 PINGRESP 協議包,則說明當前存在半連接、或者 Broker 已經下線、或者出現了網絡故障,這個時候,客戶端應當關閉當前連接。
-
Broker 流程
在連接建立后,Broker 如果沒有在 Keep Alive 的 1.5 倍時間內,收到來自客戶端的任何包,則會認為和客戶端之間的連接出現了問題,此時 Broker 便會斷開和客戶端的連接。
如果 Broker 收到了來自客戶端的 PINGREQ 協議包,需要回復一個 PINGRESP 協議包進行確認。
-
客戶端接管機制
當 Broker 內存在半連接時,如果此時對應的客戶端發起了重連、新的連接,則 Broker 會啟動客戶端接管機制:關閉舊的半連接,然后與客戶端建立新的連接。
這種機制保證了客戶端不會因為 Broker 內的半連接問題,導致無法進行重連。
如何在 EMQX 中使用 Keep Alive
在 EMQX 中,用戶可以通過配置來自定義 Keep Alive 機制的行為,主要配置字段有:
zone.${zoneName}.server_keepalive
server_keepalive 類型 默認值 整型 無
如果沒有設置這個值,則 EMQX 會按照客戶端創建連接時的 Keep Alive 的值,來控制 Keep Alive 的行為。
如果設置了這個值,則 Broker 會對該 zone 下面所有的連接,強制啟用 Keep Alive 機制,並且會使用這個值,覆蓋客戶端連接請求中的值。
zone.${zoneName}.keepalive_backoff
keepalive_backoff 類型 默認值 浮點數 0.75
MQTT 協議中要求 Broker 在 1.5 倍 Keep Alive 時間內,如果沒有收到客戶端的任何協議包,則認定客戶端斷開了連接。
而在 EMQX 中,我們引入了退讓系數(keepalive backoff),並將這個系數通過配置暴露出來,方便用戶更靈活的控制 Broker 端的 Keep Alive 行為。
在引入退讓系數后,EMQX 通過下面的公式來計算最大超時時間:
Keepalive * backoff * 2
backoff 默認值為0.75,因此在用戶不修改該配置的情況下,EMQX 的行為完全符合 MQTT 標准。
更多相關內容請參見 EMQX 配置文檔。
WebSocket 連接時設置 Keep Alive
EMQX 支持客戶端通過 WebSocket 接入,當客戶端使用 WebSocket 發起連接時,只需要在連接參數中設置上 keepalive 的值即可, 具體見使用 WebSocket 連接 MQTT 服務器。
結語
本文介紹了 MQTT 協議中 Keep Alive 的機制及 EMQX 中 Keep Alive 的使用,開發者可以借助這一特性確保 MQTT 連接的穩定性,構建更加健壯的上層物聯網應用。
版權聲明: 本文為 EMQ 原創,轉載請注明出處。