MQTT v5 (MQTT 5.0) 新特性介紹
項目中逐步完成了 MQTT 5.0的開發,這裏介紹下MQTT 5.0 的一些新特性
MQTT 5.0 規範見:http://docs.oasis-open.org/mqtt/mqtt/v5.0/cos01/mqtt-v5.0-cos01.html#_Toc514847900
格式
首先,協議上,增加了一個 Property
字段,正是這個字段,使得 MQTT 5.0 可以支持衆多的新特性。而在MQTT 3.1.1中,MQTT沒有任何可以拓展的地方,限制了MQTT拓展功能的可能性。
request/response 模式
MQTT 本身是 訂閱/推送 模式,不像HTTP那樣 請求/響應 模式。那麼MQTT是如何在 訂閱/推送 模式下支持 request/response 模式呢?
這裏簡單翻譯了 http://docs.oasis-open.org/mqtt/mqtt/v5.0/cos01/mqtt-v5.0-cos01.html#_Request_/_Response
中舉例的場景:
(1)A publish 一個消息,消息topic假設是"topicA",該消息 通過Property
攜帶了Response Topic
,假設該字段是"topicresponse"。
(2)訂閱了"topicA"的接收端B(有可能有多個)收到了該消息。
(3)B處理完"topicA"後,會publish 一個 topic 名字是 “topicresponse” 的消息。該消息有可能是A訂閱的,也有可能是其他人訂閱的。
(4)A publish 的消息,可能還會攜帶Correlation Data
屬性,假設其值是"msgresponse",這樣B發publish的消息就是(“topicresponse”, “msgresponse”)。
Server redirection
Server可以發送 CONNACK
或者 DISCONNECT
,其 Reason Codes
可以是0x9c或者0x9d,表示Client需要往另一個Server發送請求。
0x9C 類似 HTTP 的 302, 0x9d 類似 HTTP的 301。
CONNACK
或者 DISCONNECT
可以通過 Property
攜帶Server redirection
,其值可以告訴Client往哪個Server發送請求,類似HTTP的"Location"首部。
AUTH控制報文
MQTT 單純通過 CONNECT
可能無法提供足夠的信息給Server進行身份認證,所以 Server 在收到 MQTT 的 CONNECT
後,回覆 AUTH控制報文給Client,Client接着也用 AUTH
包發送附加信息,Server直到 認證完成後,纔會發送 CONNACK
。
Topic Alias
類似HTTP2
的頭部壓縮效果,當然,沒有同HPACK
那麼複雜的東西。
我們知道,PUBLISH
消息的時候,需要攜帶 topic和message,其中topic往往是固定的,那麼我們只需要第一次發送完整的 topic,並且通過Property
中攜帶Topic Alias
告知對端下次這個PUBLISH的topic會使用Topic Alias
中的值代替,Topic Alias
的值是一個整數
類型的值。
client 通過 CONNECT
中 Topic Alias Maximum
告知 Server自己能處理的最多的 Topic Alias
個數。
Server 通過 CONNACK
中 Topic Alias Maximum
告知 Client自己能處理的最多的 Topic Alias
個數。
如果當前PUBLISH消息的topic長度不爲0,那麼接受方需要解析 Topic Alias
中的值,並且 將topic和該值進行映射。
如果當前PUBLISH消息的topic爲0,那麼接受方需要解析 Topic Alias
中的值,用該值去查找對應的topic。
User Property
自定義屬性,可以添加兩端約定的數據。例如可以加入類似HTTP的 "Header:value"信息。MQTT本身沒有類似HTTP的HOST信息,我們可以使用User Property
特性讓MQTT支持。
Session Expiry Interval
之前的MQTT版本,當cleansession爲0時,server和client會嘗試保存session信息(sub信息、PUBLISH狀態等),但是有個問題,server 不知道需要保存這個session多久。MQTT 5.0 就 在 Property
字段中增加了Session Expiry Interval
屬性來告知server這個session希望被保存多久。
如果MQTT 5.0 不攜帶 Session Expiry Interval
或者 Session Expiry Interval
設置爲0,server和client則不會保存session信息。
如果Session Expiry Interval
設置爲0xffffffff,則表示session永遠不會老化。
當然,這個字段是需要配合Clean Start
使用的,如果Clean Start
爲1,那麼 Session Expiry Interval
設置多大都無意義。
CONNECT、CONNACK、DISCONNECT都會發送 Session Expiry Interval
字段。DISCONNECT
中攜帶該字段可以告知Server更新老化時間。
CONNACK中的Session Expiry Interval
只有當CONNECT不攜帶該字段時纔有用,當client攜帶該字段,server發送該字段只是表明自己最大的老化時間,不會強制client必須按照這個值。
Maximum QoS
Server 可以發送 Maximum QoS
屬性告知Client自己支持最大的Qos是多少,Client發送的PUBLISH的Qos必然不能大於該值。
Receive Maximum
告知對方自己希望處理未決
的最大的 Qos1 或者 Qos2 PUBLISH消息個數,如果不存在,則默認是65535。
作用:流控。
因爲當處理 Qos > 0 的PUBLISH的時候,需要回復對端PUBACK、PUBREC PUBCOMP等。Receive Maximum
屬性提供了告訴對端發送Qos>0的PUBLISH的速率,對端發現未決PUBLISH個數等於Receive Maximum
時,不能再發送Qos > 0 的PUBLISH消息了。
Maximum Packet Size
顧名思義,單個 MQTT控制報文 的大小,如果不攜帶,表示不限制。
這個大小指整個 MQTT控制報文 的大小。對端如果發現將發送的包大於該大小,就默默丟棄,不關閉連接。如果自己收到超過自己通告的Maximum Packet Size
需要關閉連接。
Topic Alias Maximum
作用見上文Topic Alias
。
Reason Code
MQTT 3.1.1 只有CONNACK有是否成功還是失敗的標誌位,現在MQTT 5.0所有的ACK都有該標誌位。具體各個ACK中code值得含義在規範中有定義,這裏不再列舉。
需要注意的是,SUBACK中,MQTT 3.1.1 的 Granted Qos
被取代爲Reason Code
,Reason Code
中有狀態碼錶示了具體的Granted Qos
。
如果PUBLISH是成功的,其ACK的的Reason Code
可以不添加。
Reason String
所有的ACK以及DISCONNECT 都可以攜帶 Reason String
屬性告知對方一些特殊的信息,一般來說是ACK失敗的情況下會使用該屬性告知對端爲什麼失敗,可用來彌補Reason Code
信息不夠。
Clean Start
Clean Start
取代了 MQTT3.1.1 中 CleanSession,在協議格式上,直接佔用了CleanSession
原本的field,這也表示Clean Start
語義上和 CleanSession
是一樣的。
Payload Format Indicator
指定了PUBLISH 消息的message部分是utf8格式的還是二進制的,接收方必須驗證payload是否是該屬性定義的格式。
Payload Format Indicator
爲 0,表示 是二進制,和不攜帶該屬性的語義是一樣的。
Payload Format Indicator
爲 1,表示 是utf8編碼數據。
Message Expiry Interval
指定了PUBLISH數據在Server的最長等待時間。超過這個時間,這個數據不能被publish到匹配topic的subscriber
還有其他的細枝末節不再展開了,上述衆多屬性也有一些細節的地方,可以在原文中搜索就直到了。