MQTT (Message Queuing Telemetry Transport,消息隊(duì)列遙測(cè)傳輸) 是一種標(biāo)準(zhǔn)化的發(fā)布/訂閱消息傳輸協(xié)議,設(shè)計(jì)于1999年,最初是為了在衛(wèi)星之類(lèi)的物體上使用。它是一個(gè)非常輕量級(jí)的協(xié)議,由于對(duì)帶寬需求很低,從而成為了 M2M 通信或物聯(lián)網(wǎng)應(yīng)用的理想選擇,現(xiàn)在已經(jīng)成為這類(lèi)場(chǎng)景最常見(jiàn)的協(xié)議之一。
本文會(huì)對(duì)該協(xié)議及一些使用范例做以簡(jiǎn)介,雖然沒(méi)打算寫(xiě)成 MQTT 的綜合性參考指南,但會(huì)提供足夠的信息,讓開(kāi)發(fā)人員了解到如何安裝運(yùn)行這一協(xié)議。如果想要更深入地了解,可以參考 HiveMQ 所發(fā)布的系列文章。
發(fā)布/訂閱
發(fā)布/訂閱,通常也被成為 pub-sub 模式是 MQTT 的核心,除了基于同一個(gè)消息代理的發(fā)布者和訂閱者之外,還有一些其它節(jié)點(diǎn)圍繞著該消息代理呈星型拓?fù)浞植?。這個(gè)模型與標(biāo)準(zhǔn)的客戶(hù)端/服務(wù)器迥然不同,一開(kāi)始看似有些奇怪,但它提供的去耦能力在很多情況下都有巨大的優(yōu)勢(shì)。
客戶(hù)端可以發(fā)布或訂閱特定的主題(topic,有些類(lèi)似信息主題),根據(jù)使用它們的消息代理來(lái)決定誰(shuí)會(huì)收到信息。MQTT 的主題有特定的語(yǔ)法,使用斜杠(/)作為分隔符,整體呈層次結(jié)構(gòu),非常類(lèi)似 URL 中的路徑格式,因此廚房中的溫度傳感器也許會(huì)發(fā)布到類(lèi)似“sensors/temperature/home/kitchen” 這樣的主題。
我們看一個(gè)例子:想象一下有一個(gè)網(wǎng)絡(luò),將全世界的溫度傳感器連接起來(lái),提供氣象服務(wù)。所有這些傳感器保持與某個(gè)消息代理中間件相連接,每隔10分鐘報(bào)告一次當(dāng)前的溫度。他們基于自身位置按照下面的格式向特定主題發(fā)布信息:
sensors/temperature/{country}/{city}/{street name}
那么在倫敦貝克街(Baker Street)的某個(gè)傳感器就會(huì)向“sensors/temperature/uk/london/baker_street”發(fā)布一條包含當(dāng)前溫度的信息。

MQTT 示例拓?fù)?/p>
氣象服務(wù)需要保證歷史溫度數(shù)據(jù)庫(kù)的數(shù)據(jù)最新,因此創(chuàng)建了訂閱到 MQTT主題的數(shù)據(jù)庫(kù)服務(wù),數(shù)據(jù)庫(kù)服務(wù)會(huì)在收到最新溫度信息時(shí)發(fā)出提示。不過(guò)這里存在一個(gè)問(wèn)題:數(shù)據(jù)庫(kù)服務(wù)需要了解到全世界所有的溫度傳感器,而將每個(gè)傳感器訂閱到獨(dú)立的主題會(huì)非常復(fù)雜,幸好 MQTT 有相應(yīng)的解決方案:通配符(wildcards)。
通配符
在 MQTT 中有兩個(gè)可用的通配符,分別是+和#,+表示匹配單一層級(jí)中的任意主題,#表示匹配任意數(shù)量的層次。因此在全球溫度數(shù)據(jù)庫(kù)中可能會(huì)有訂閱到 sensors/temperature/# 的服務(wù),它能從全世界的任何一個(gè)傳感器接收溫度讀數(shù)。但如果英國(guó)政府想要在自己的溫度服務(wù)中利用這些數(shù)據(jù),只要訂閱到 sensors/temperature/uk/# ,就可以限制范圍,只接受英國(guó)的傳感器讀數(shù)。如果某個(gè)服務(wù)想要接收某個(gè)特定位置所有類(lèi)型的傳感器數(shù)據(jù),可以使用類(lèi)似這樣的格式:
sensors/+/uk/london/bakerstreet_
正如你所見(jiàn),這是一個(gè)極優(yōu)秀的模塊化系統(tǒng),添加新的傳感器與數(shù)據(jù)庫(kù)只是小事一樁。而且該系統(tǒng)在性能方面也很優(yōu)秀,MQTT 消息代理可以高度并行化并采用事件驅(qū)動(dòng),從而使得單個(gè)消息代理可以輕易擴(kuò)展到每秒處理數(shù)萬(wàn)條信息的級(jí)別。
服務(wù)質(zhì)量(QoS)
MQTT 的設(shè)計(jì)初衷是為了在不可靠的網(wǎng)絡(luò)中運(yùn)作良好,為不同的場(chǎng)景提供了三個(gè)級(jí)別的服務(wù)質(zhì)量,允許客戶(hù)端指定自己想要的可靠性級(jí)別。
QoS Level 0:至多一次
這是最簡(jiǎn)單的級(jí)別,無(wú)需客戶(hù)端確認(rèn),其可靠性與基礎(chǔ)網(wǎng)絡(luò)層 TCP/IP 一致。
QoS Level 1:至少一次,有可能重復(fù)
確保至少向客戶(hù)端發(fā)送一次信息,不過(guò)也可發(fā)送多次;在接收數(shù)據(jù)包時(shí),需要客戶(hù)端返回確認(rèn)消息(ACK 包)。這種方式常用于傳遞確保交付的信息,但開(kāi)發(fā)人員必須確保其系統(tǒng)可以處理重復(fù)的數(shù)據(jù)包。
QoS Level 2:只有一次,確保消息只到達(dá)一次
這是最不常見(jiàn)的服務(wù)質(zhì)量級(jí)別,確保消息發(fā)送且僅發(fā)送一次。這種方法需要交換4個(gè)數(shù)據(jù)包,同時(shí)也會(huì)降低消息代理的性能。由于相對(duì)比較復(fù)雜,在 MQTT 實(shí)現(xiàn)中通常會(huì)忽略這個(gè)級(jí)別,請(qǐng)確保在選擇數(shù)據(jù)庫(kù)或消息代理前檢查這個(gè)問(wèn)題。

在 MQTT 中的服務(wù)質(zhì)量水平劃分