2014年2月5日

MQTT(二)Message Type and Flows

Message Type

在MQTT協定裡,當Client要連上MQTT Server時,需要發送一個type為"CONNECT"的訊息到MQTT Server,才能開始建立起連線;當Client想發佈訊息時,則要發送一個type為"PUBLISH"的message出去;而當Client要訂閱某個Topic時,需要發送一個type為"SUBSCRIBE"的message出去。MQTT協定需要依照這些不同的type message,來完成訊息傳遞工作的。
下面就先列出,當前版本3.1所有的Message Type:
名稱 代表值 說明
Reserved 0 保留之後使用
CONNECT 1 Client對Server發出連線請求
CONNACK 2 連線請求的Ack
PUBLISH 3 發佈訊息
PUBACK 4 發佈訊息Ack(QoS level 1使用)
PUBREC 5 已收到發佈訊息(QoS level 2使用)
PUBREL 6 釋放發佈訊息(QoS level 2使用)
PUBCOMP 7 訊息發佈完成(QoS level 2使用)
SUBSCRIBE 8 Client請求訂閱
SUBACK 9 請求訂閱的Ack
UNSUBSCRIBE 10 Client取消訂閱
UNSUBACK 11 取消訂閱的Ack
PINGREQ 12 PING Request
PINGRESP 13 PING Response
DISCONNECT 14 Client斷線
Reserved 15 保留之後使用
光從Message Type的名稱,其實就可以猜出其中一些訊息的應用。不過如果能搭配整個流程來看,會比較清楚知道在各種場景下會使用哪些訊息。

Flows

下面根據幾個應用場景,說明訊息傳遞的順序與方向:

1.CONNECT

當client對server建立起TCP/IP socket連線時,一個protocol level session會根據CONNECT flow被建立。

Client Message and direction Server
CONNECT
----------->
Action: According set flag to create session.
CONNACK
<-----------
如果發送的CONNECT message為不正確的格式,則server會直接關閉連線。

2.DISCONNECT

client會對server發送DISCONNECT message,表示它要關閉TCP/IP連線。如果當初client在連線時有設定clean session flag,則所有跟此client相關的資訊都會被清除。
Client Message and direction Server
DISCONNECT
--------------->
Action: Clean user infomation if clean session set.


3.PUBLISH

publish會因為所選的QoS而有以下三種flow:

a. QoS level 0: At most once delivery

訊息會根據底層的TCP/IP網路盡最大努力傳送。並且沒有預期會有任何的response,也沒有定義任何訊息重新傳送的語義。訊息要嘛送到server一次,要嘛什麼都沒送達。
下表顯示QoS level 0 protocol的flow:
Client Message and direction Server
QoS = 0 PUBLISH
----------->
Action: Publish message to subscribers

b. QoS level 1: At least once delivery

server會把PUBACK message當作ack回傳。如果在通訊連線斷線或是裝置出現錯誤,或是client沒有在一個特定時間之內收到server發送的ack message,則client要重發message並且設定message header的DUB bit。訊息至少會到達server一次。
QoS level 1會在message header內包含Message ID。
下表顯示QoS level 1 的流程:

Client Message and direction Server
QoS = 1
DUP = 0
Message ID = x

Action: Store message
PUBLISH
---------->
Action:
  • Sotre message
  • Publish message to subscribers
  • Delete message
Action: Discard message PUBACK
<----------
當server重複收到client發送來的訊息,server一樣會把訊息publish給所有的subscriber,然後發送另一個PUBACK message回給client。

c. QoS level 2: Exactly once delivery

對上面描述的QoS level 1 protocol額外增加流程來確保重複發送的訊息不會被發送到接收訊息的application。這是最高level的發送,應用在當重複的message不被允許時的狀況(如金流資料)。它可能會增加網路流量,但因為訊息內容很重要,因此這通常是會被接受的。
QoS level 2的訊息會在message header有一個Message ID。
下表顯示QoS level 2的flow。其中在Server Side有兩個語義可以讓一個收件人決定應該要如何處理PUBLISH的流程。它們只差在訊息何時會被發佈給subscriber而已。選擇的語義不會影響到QoS level 2流程訊息只會收到一次的保證。



Client Message and direction Server
QoS = 2
DUP = 0
Message ID = x

Action: Store message
PUBLISH
---------->
Action: Store message

or

Actions:
  • Sotre message
  • Publish message to subscribers
PUBREC
<----------
Message ID = x
Message ID = x PUBREL
---------->
Actions:
  • Publish message to subscribers
  • Delete message
or

Action: Delete message ID
Action: Discard message PUBCOMP
<----------
Message ID = x
如果有錯誤發生或是timeout了,則protocol的flow會從最後沒有ack的message開始嘗試,也就是說要嘛重新發送PUBLISH message,要嘛重新發送PUBREL message。QoS level 2這些額外的Protocol flows確保訊息只會被送到訂閱者一次。

4.SUBSCRIBE

SUBSCRIBE message允許client對server上有興趣的一個或多個topic進行註冊。如果有訊息被publish到了某個topic內,則server會把訊息PUBLISH到註冊到此topic的client。
client可以針對每個想要subscribe的topic,分別調整其QoS,舉例來說當前client subscribe兩個topic,分別為"a/b" topic 和 "c/d" topic,則client可以決定"a/b"要以QoS 0來接收,而"c/d"要以QoS 1來接收。
當然client會收到的真正QoS level,還是要依據原本PUBLISH message來決定,有可能會小於或等於client設定的。舉例來說,今天一個client對"a/b"這個topic做了QoS 1的subscribe。則:
  • QoS level 0 PUBLISH message會根據QoS 0來發送此訊息給此client,
  • QoS level 2 PUBLISH message會根據QoS 1來發送此訊息給此client。
也就是說publisher有責任決定此則訊息的最大QoS level為何,但是每個subscriber也可以依照自己的使用狀況來決定適合的QoS level。

Client Message and direction Server
SUBSCRIBE
----------->
SUBACK
<-----------

5.PING

一個連線中的client,可以發送PINGREQ message,詢問server是否還活著。之後server會回應一個PINGRESP message,告訴client它還活著。

Client Message and direction Server
PINGREQ
----------->
PINGRESP
<-----------

小結

本篇介紹了MQTT的各種Message Type,並且由Flow來觀察每種Message會應用在何種場景,藉此加深印象。

參考:

MQTT V3.1 Protocol Specification