2014年3月16日 星期日

MQTT(五)SUBSCRIBE Message

前言:

上一篇提到用來發佈訊息的PUBLISH Message,接著就來談談訂閱訊息用的SUBSCRIBE Message。

SUBSCRIBE Message

SUBSCRIBE Message允許client對Server上一或多個感興趣的主題(Topic)進行訂閱。當有訊息對主題發佈時,server會將訊息當作PUBLISH Message送給訂閱的client。SUBSCRIBE Message也定義了QoS level,表示它期望以何種QoS level來接收訊息。

Fixed Header:

bit76543210
byte 1Message Type(8)DUP flagQoS levelRETAIN
1000001x
byte 2Remaining Length
上面為SUBSCRIBE Message裡面的fixed header,以下依依介紹它們的作用。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是SUBSCRIBE Message的關係,因此會填上1000。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,會用在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE上。當client或是server要重新傳送上述訊息時,則要將此flag設為1。此flag會適用於QoS大於0的訊息。
    此flag 只能當成一種提示,表示此則訊息可能在之前有收過了,不應該拿它來當成訊息重複的檢查flag。
  • QoS level:SUBSCRIBE Message使用QoS level 1來回應(acknowledge)不同的訂閱主題請求。
  • RETAIN:沒有使用到。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。

Variable Header:

由於SUBSCRIBE Message QoS level為1,因此其variable header會包含Message ID,用來確保訊息能夠正確傳送。
下面為SUBSCRIBE Message,variable header欄位範例:
FieldValue
Message ID10

Payload:

SUBSCRIBE Message的payload會包含一個主題名稱列表,代表該Client想要訂閱的主題,列表內的每個主題都會包括一個期望接收訊息時的QoS level,可以參考MQTT(二)Message Type and Flows:Subscribe Flow來了解QoS level與其影響為何。
主題的名稱可以使用萬用字元(wildcard characters),關於萬用字元稍後會進行說明,以下為SUBSCRIBE Message的payload範例:
Topic name"a/b"
Requested QoS1
Topic name"c/d"
Requested QoS2
上述範例代表該Client想要訂閱兩個主題"a/b"、"c/d",其中主題"a/b"期望用QoS level 1來接收訊息,主題"c/d"期望用QoS level 2來接收訊息。

Response:

當Server接收到從Cleint發送過來的SUBSCRIBE Message,則回應一個SUBACK Message給client。
Server有基於Client已經訂閱的關係,因此可能會開始傳送PUBLISH Message給Client,即使Client還沒收到SUBACK Message。
Server有可能會降低cleint請求的QoS level。這會發生在Server沒辦法提供高level的QoS時。舉例來說,如果Server沒有提供一個可靠的訊息持久機制(persistence mechanism),則它可能只提供QoS level 0給訂閱者。Server提供的QoS level會在SUBACK Message的payload內,依照主題的訂閱順序回應給訂閱者。以下為範例:
Granted QoS0
Granted QoS2

主題萬用字元(Topic WildCard Characters):

在訂閱的時候可以使用特出字元,允許你一次訂閱多個主題,此字元稱為萬用字元。
主題層級分隔符號(Topic level separator)被用來對主題做結構化。單一層級的萬用字元和多層級的萬用字元可以被用在訂閱上面,但是不能被用在發佈(publish)訊息上面,也就是說在發佈訊息時,主題要明確定義,不能用萬用字元來同時對多個主題做訊息發佈。

Topic level separator(主題層級分隔符號):

斜線符號(/)用來切割topic tree的每個層級,提供一個有層次的主題空間。使用主題層級分割符號來切割主題,在遇到用萬用字元訂閱該主題時是很有用的,下面接著介紹兩個萬用字元。

Multi-level wildcard(多層級萬用字元):

井字號(#)用來匹配任何層級的主題。舉例來說,如果你用此萬用字元訂閱了 finance/stock/ibm/#,則你將會收到來自於下列主題的訊息:
  • finance/stock/ibm
  • finance/stock/ibm/closingprice
  • finance/stock/ibm/currentprice
多層級萬用字元可以表示零到多個層級,因此 finance/# 可以匹配到finance 。
多層級萬用字元在以下狀況是有效的,如 # 或是 finance/# ,而以下狀況下是無效的,如 finance# 和 finance/#/closingprice 。

Single-level wildcard(單一層級萬用字元):

加字號(+)用來匹配單一層級的主題。舉例來說 finance/stock/+ 會匹配 /finance/stock/ibm 和 /finance/stock/xyz ,但是不會匹配到finance/stock/ibm/closingprice 。也由於它只會匹配到一個層級,因此 finance/+ 不會匹配到 finance 。
單一層級萬用字元可以使用在任何層級的主題樹,也可以和多層級萬用字元結合使用。
單一層級萬用字元在以下狀況是有效的,如 + 和 finance/+ 以及finance/+/ibm 。而以下狀況是無效的,如 finance+ 。

小結

本篇介紹了MQTT的SUBSCRIBE Message,此訊息用於訂閱主題上,而每個想訂閱的主題需要設定期望的QoS level,藉此來表達client對該主題的訊息品質需求。
另外也介紹了主題萬用字元,讓client在訂閱主題時,可以透過萬用字元同時對多個主題進行訂閱。

參考:

MQTT(四)PUBLISH Message

前言:

上一篇提到建立起連線用的CONNECT Message,接著來談談和發佈訊息有關的Message,PUBLISH Message。

PUBLISH Message

PUBLISH Message是發佈訊息時會用到的訊息類型,它會使用在兩個方向:
  1. client對某個主題(Topic)散佈訊息,此時它會發送PUBLISH Message給Server。
  2. server收到了client發送給某個主題的訊息,server會把這些訊息已PUBLISH Message的方式發送給訂閱此主題的client。
每個PUBLISH Message都會包含一個topic name,代表此訊息要發送給哪個主題。

Fixed Header:

bit76543210
byte 1Message Type(1)DUP flagQoS levelRETAIN
00110010
byte 2Remaining Length
上面為PUBLISH Message裡面的fixed header,以下依依介紹它們的作用。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是PUBLISH Message的關係,因此會填上0011。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,會用在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE上。當client或是server要重新傳送上述訊息時,則要將此flag設為1。此flag會適用於QoS大於0的訊息。
    此flag 只能當成一種提示,表示此則訊息可能在之前有收過了,不應該拿它來當成訊息重複的檢查flag。
  • QoS level:設定此訊息的QoS level,只有在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE才會用到。可以參考MQTT(二)Message Type and Flows:PUBLISH flow來得知比較詳細的資訊。
  • RETAIN:設定訊息是否要保留在server上,此特性只有PUBLISH才會用到。當client發送PUBLISH Message給Server上的某個Topic時,如果將此flag設為1,則Server將此訊息發佈給當前的所以訂閱者後,必須將此訊息保留。
    當有一個新的client對此Topic進行訂閱,則Server必須把最後一則Retain flag設為1的訊息傳送給該client。被設為Retain的訊息必須保留直到Server重啟為止。
    此機制會適用於訊息與訊息之間會有一段時間的場景,也就是說,訊息的發佈(Publish)可能不是那麼的頻繁,如錯誤回報的系統。它可以讓新的訂閱者馬上知道上次的最新狀況為何。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。

Variable Header:

PUBLISH Message的Variable header會包含以下欄位:
  • Topic name:
    一個UTF的編碼字串,它必須是一個明確的主題定義。不能為萬用字元(wildcard characters),關於萬用字元會在後面的篇幅做介紹。這邊只需知道,當訂閱者用萬用字元訂閱到此主題時,此訂閱者收到的PUBLISH訊息裡面的Topic name欄位會是完整的名稱,而不是用萬用字元匹配到的名稱。
  • Message ID:
    Message ID會使用在QoS level 1或是2的下列訊息上面:PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK。
    Message ID為16bit無符號的整數,代表特定方向訊息唯一的id,每個client都會維護他們自己的Message ID列表。所以有可能會有一種狀況發生,就是某個client在發佈Message ID為1的訊息給server時,同時收到Server發佈過來Message ID為1的訊息。
    Message ID不能為0,它會被視為無效的Message ID。
    下面為PUBLISH Message QoS level為1時,variable header欄位範例:
FieldValue
Topic Name:"a/b"
Message ID10

Payload:

PUBLISH Message的payload會包含要發佈的訊息內容。Payload長度為0的訊息是有效的。

Response:

PUBLISH Message的回應會跟QoS level有關係,下表顯示QoS level與預期的回應:
Qos LevelExpected response
Qos 0None
QoS 1PUBACK
QoS 2PUBREC
PUBLISH Message可以是從client發佈給Server,或者是從server發佈給訂閱者。在收到訊息時,根據QoS level會做以下的動作:
  • QoS 0:
    將訊息提供給任何有興趣的訂閱者。
  • QoS 1:
    將訊息記錄到儲存裝置(persistent storage),將它提供給任何有興趣的訂閱者,然後回傳PUBACK給發送端。
  • QoS 2:
    將訊息記錄到儲存裝置,不要馬上將它提供給任何有興趣的訂閱者,先回傳PUBREC給發送端。
可以參考MQTT(二)Message Type and Flows:PUBLISH flow來得知比較詳細的資訊。

小結

本篇介紹了MQTT的PUBLISH Message,PUBLISH Message其實要注意的就是QoS level和Retain這兩個特性,QoS level會影響到訊息的可靠度,而Retain可以讓新的訂閱者在訂閱主題時就能得知此主題最新的狀態。了解這兩個特性會可以幫助整體服務架構的規劃。
另外還需要注意到,一次只能對一個Topic發佈訊息,所以沒辦法做到一次同時對多個Topic發不訊息。

參考:

MQTT(三)CONNECT Message


前言:

前一篇提到MQTT有很多種Message Type用來實現協定。
而這次會特別把CONNECT Message拿出來講,主要是因為在CONNECT Message裡面有用到了許多的flag,而這些flag又會跟MQTT的一些特性有關,因此有必要將之獨立出來說明。

Message Format

在開始談CONNECT message之前,讓我們先來看看MQTT的訊息格式。 MQTT的訊息格式如下圖所示:

其中:
  • Fixed Header每個類型的訊息都會有,至少為2 byte。
  • Variable Header會根據訊息類型而有所不同,某些訊息類型甚至沒有variable header。
  • Payload和Variable Header一樣,也會根據訊息類型不同而有所不同,某些訊息類型沒有Payload。

CONNECT Message

接著讓我們來看看今天的主角CONNECT Message,首先先看看它的Fixed Header。

Fixed Header

bit76543210
byte 1Message Type(1)DUP flagQoS levelRETAIN
0001xxxx
byte 2Remaining Length
在CONNECT Message裡面,fixed header並不會用到太多欄位,因此這邊只會簡單介紹一下他們。
  • Message Type:每種類型的Message都要用到,要根據想用的訊息類型填上相對應的值,值可以參考先前貼的文章MQTT(二)Message Type and Flows。這邊由於是CONNECT Message的關係,因此會填上0001。
  • DUP flag:標記此訊息為重複(duplicate)的訊息,只有在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE才會用到。
  • QoS level:設定此訊息的QoS level,只有在PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE才會用到。
  • RETAIN:設定訊息是否要保留在server上,此特性只有PUBLISH才會用到。
  • Remaining Length:此欄位記錄當前的Message,它的Variable header和Payload總共的長度為何,此欄位不一定就是1 byte,它是可變得,最多到4 byte。而且它會用特殊編碼來存放值,最高可以呈現到256MB,也就是說,你的Variable header + payload最大可以達到256MB。至於它編碼的部分可以去參考MQTT V3.1 Protocol Specification, Fixed header的介紹,會寫的比較詳細,這邊就不再多描述了。
看完上述的介紹之後會發現到,CONNECT Message的Fixed Header其實沒用到什麼特別的flag,只需要定對Message Type,然後根據編碼方式寫上正確的Remaining Length即可。
接著讓我們繼續往下看,再來是第二個Herader,也就是Variable Header。

Variable Header:

下面為一個CONNECT Message其Variable Header範例:
Description76543210
byte1 - byte8Protocol Name (MQIsdp)
byte9Version (3)
Connect Flags
byte 10User name flag (1)
Password flag (1)
Will RETAIN (0)
Will QoS (01)
Will flag (1)
Clean Session (1)
1100111x
byte 11Keep Alive MSB (0)00000000
byte 12Keep Alive LSB (10)00001010
主要分為三塊,分別為協定的資訊(byte1 ~ byte9)、此次連線的特性設定(byte 10)以及連線逾時時間設定。以下說明這些flag的用意:

Protocol name 和 Protocol version

協定的資訊包括協定的名稱和版本號碼,名稱為MQIsdp,版本號碼為3(0x03)。

Connect flags:

Connect flag原本有四個,分別為Clean session、Will、Will QoS和Retain flags,而MQTT3.1又新增了兩個Username和Password,底下就來一一介紹他們。
  • clean session flag
    設定為0,代表是當client斷線時,server必須要把該位client訂閱哪個主題記錄下來。再該client斷線的期間,如果有QoS 1和QoS 2的訊息被發佈到該主題了,則server必須把訊息儲存下來,等到該client重新連線時能收到它沒收到的訊息。
    設定為1,代表當client斷線時,server必須要清掉該位client所有的狀態,當client重新連線時,必須要再重新訂閱它感興趣的主題。
  • will flag、will QoS和will Retain flag
    這三個flag,就是在MQTT簡介裡被提到的 最後遺囑(Last Will and Testament) 機制所用的flag。這機制是這樣的,client在一開始發送CONNECT訊息給server要求建立連線時,就把要對哪個主題說什麼遺言一起傳給server,當它在不正常的情況下斷線時(比如說網路連線斷掉、裝置故障等等),則這些訊息就會被server主動發佈到該主題上。如果是client主動發送DISCONNECT訊息給server要求斷線時,則此機制將不會有作用。
    要啟動此機制,首先就是要將Will flag設為1,這樣就代表要啟用,之後你設定遺言的QoS level為何,server會依照你設定的QoS level來幫你傳送訊息,最後設定此此則遺言是否要保留(Retain)在server上。如果有設定Will flag,則在pyaload內會需要定義Will Topic和Will Message,也就是要對哪個主題發送什麼樣的遺言。
  • Username and Password flag
    最後兩個flag為Useername和Password,意思是說此連線是否會包含帳號與密碼,如果有設定,則需要在payload內把帳號和密碼一起傳給server。要注意的是Password flag有設定而Username flag沒設定,此狀況是不被允許的。

Keep Alive timer

以秒為單位,指的是當server多久沒接收到從client發送過來的訊息時,就要認為與該client的網路連線已經斷掉了。此設定可以讓server不需要等待時間較長的TCP/IP timeout來得知網路狀況。Client有責任在此定義的時間內對server發過來的訊息作回應。如果在這時間內client和server都沒有訊息互傳的話,則client必須發送一個PINGREQ訊息給server,而server則回應一個PINGRESP message。
server會給client一個寬限時間,也就是會等1.5個Keep Alive timer時間,如果此段時間內client都沒送訊息過來,則server必須將此client斷線。
而client如果在Keep Alive time期間發送出PINGREQ訊息,卻一直沒收到PINGRESP訊息,則client必須關閉TCP/IP socket連線。
Keep Alive為2 byte,設定為0代表client不會斷線,通常只會設定幾分鐘。而此設定的最大值約為18小時。

Payload:

最後為CONNECT Message的payload,payload裡面包含什麼會跟你在variable header內的設定有關係,以下就來介紹payload裡面有些什麼。

Client Identifier

client唯一的識別碼,此識別碼在處理QoS level 1和2時會用到。長度限制為1~23個字,若超過23個字則會發生 Identifier Rejected的錯誤。

Will Topic and Will Message

如果在variable內有設定Will flag的話,代表此連線將要啟用最後遺囑(Last Will and Testament)機制,則payload就必須包含遺言內容和遺言要發送到哪個主題。

Username and Password

如果在variable內有設定Username flag和Password flag的話,代表此連線需要帳號與密碼,則payload就必須包含帳號和密碼。

小結

本篇介紹了MQTT的CONNECT Message,並介紹了一些MQTT的特性,讓程式開發人員在使用MQTT的相關library開發時,會知道建立連線可以設定的參數為何,其意義又為何。了解這些特性也會對應用MQTT的的架構規劃有所幫助。

參考:

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:
名稱代表值說明
Reserved0保留之後使用
CONNECT1Client對Server發出連線請求
CONNACK2連線請求的Ack
PUBLISH3發佈訊息
PUBACK4發佈訊息Ack(QoS level 1使用)
PUBREC5已收到發佈訊息(QoS level 2使用)
PUBREL6釋放發佈訊息(QoS level 2使用)
PUBCOMP7訊息發佈完成(QoS level 2使用)
SUBSCRIBE8Client請求訂閱
SUBACK9請求訂閱的Ack
UNSUBSCRIBE10Client取消訂閱
UNSUBACK11取消訂閱的Ack
PINGREQ12PING Request
PINGRESP13PING Response
DISCONNECT14Client斷線
Reserved15保留之後使用
光從Message Type的名稱,其實就可以猜出其中一些訊息的應用。不過如果能搭配整個流程來看,會比較清楚知道在各種場景下會使用哪些訊息。

Flows

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

1.CONNECT

當client對server建立起TCP/IP socket連線時,一個protocol level session會根據CONNECT flow被建立。
ClientMessage and directionServer
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相關的資訊都會被清除。
ClientMessage and directionServer
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:
ClientMessage and directionServer
QoS = 0PUBLISH
----------->
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 的流程:
ClientMessage and directionServer
QoS = 1
DUP = 0
Message ID = x

Action: Store message
PUBLISH
---------->
Action:
  • Store message
  • Publish message to subscribers
  • Delete message
Action:Discard messagePUBACK
<----------
當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流程訊息只會收到一次的保證。
ClientMessage and directionServer
QoS = 2
DUP = 0
Message ID = x

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

or

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

Action: Delete message ID
Action:Discard messagePUBCOMP
<----------
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。
ClientMessage and directionServer
SUBSCRIBE
----------->
SUBACK
<-----------

5.PING

一個連線中的client,可以發送PINGREQ message,詢問server是否還活著。之後server會回應一個PINGRESP message,告訴client它還活著。
ClientMessage and directionServer
PINGREQ
----------->
Action: Publish message to
PINGRESP
<-----------
Action: Publish message to

小結

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

參考:

MQTT(一)簡介

前言

會知道MQTT協定,要先回憶起兩年前,當初想找找Android的Push Notification的解決方案,先是找到了當時GCM的前身C2DM,以為Google已經提供了此服務,測試了一下code也蠻容易上手的,結果發現到他有quota限制,不適合拿來當成產品,因此就放棄它,改找別的解決方案,最後找到了兩種不同的實作方式,一種透過XMPP協定來完成,另一種也就是今天要提到的,透過MQTT來完成。

所以MQTT是什麼?

MQTT的全名為 Message Queuing Telemetry Transport,為IBM和Eurotech共同製定出來的protocol,在MQTT的官網可以看到一開始它對MQTT的介紹:
MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport.
簡單來說,它是為了物聯網而設計的protocol,並且它是透過publish/subscribe的方式來做訊息傳送。由於是為了物聯網而設計的協定,因此它所需要的網路頻寬是很低的,而所需要的硬體資源也是低的。

Publish/Subscribe:

在看MQTT之前,最好要先知道Publish/Subscribe的訊息傳送機制為何,這樣之後在看其協定時,才會更快上手。Publish/Subscribe有三種主要的組成元件,分別為Publisher、Subscriber以及Topic。
Publisher為訊息的來源,它會將訊息發送給Topic,而Subscriber向Topic註冊,表示他們想要接收此Topic的訊息;因此當有某個Publisher對Topic發送訊息時,只要是有對此Topic註冊的Subscriber,都會收到此則訊息。
它們的關係如下圖:

MQTT特性:

了解了Publish/Subscribe的機制之後,讓我們來看看MQTT有哪些特性:
  1. Publish/Subscribe的訊息傳送模式,來提供一對多的訊息分配。
  2. A messaging transport that is agnostic to the content of the payload.
  3. 使用TCP/IP來提供基本的網路連結。
  4. 三種訊息傳送服務的qualities:
    • "At most once",最多一次,訊息遺失或是重複發送的狀況可能會發生;這種quality適合應用在環境感測,不在意資料是否會遺失,因為下一次的資料取樣很快就會被published出來。
    • "At least once",至少一次,這種quality保證訊息會送達,只是可能會發生重複發送訊息的狀況。
    • "Exactly once",確定一次,確認訊息只會送到一次。這種quality適合用在計費系統,系統只要有重複收到資料、或是資料遺失狀況發生,就會造成系統錯誤。
  5. 由於他的header固定長度為2byte,因此可以減少封包傳送時的額外負載,並減少所需的網路頻寬。
  6. 當異常斷線發生時,會使用最後遺囑(Last Will and Testament)的機制,通知各個感興趣的client。

MQTT現況:

MQTT現階段並不是一個標準化的Protocol,還在持續改進中,目前為MQTT V3.1。不過IBM已於2013年已經將它交給OASIS進行標準化了,並且一直以來IBM對此協定採開放、免授權費的方式讓它能夠被散佈,因此相信不久的將來會成為一個主流的Protocol。
而目前支援MQTT的Client API,有Eclipse Phno Project有對MQTT client支援,其支援C、Java、Javascript、C++等等的語言,可說是支援度很高的Project。而目已經在應用MQTT的,最知名的應該就是Facebook Message App了吧,可以參考此篇文章。

小結:

上面提到的,低頻寬、低硬體需求的特性,訊息傳遞為Publish/Subscribe的方式,正好可以用來實現Push Notification的機制,並且能達到手持裝置省電的需求,接下來會先從其Protocol開始了解,並用Client Api跑些範例來應用此Protocol。

參考: