想象一下沥曹,我們有幾十個不同的設(shè)備,它們之間必須交換數(shù)據(jù)碟联。
這些設(shè)備是物聯(lián)網(wǎng)(IoT)板妓美,上面連接了幾十個傳感器。我們有以下具有不同處理能力的物聯(lián)網(wǎng)板鲤孵。Raspberry Pi 3, Raspberry Pi Model B, Intel Edison, and Intel Joule 570x. 這些板子中的每一塊都要能夠發(fā)送和接收數(shù)據(jù)壶栋。此外,我們希望許多移動設(shè)備能夠發(fā)送和接收數(shù)據(jù)普监,其中一些設(shè)備運(yùn)行iOS贵试,另一些運(yùn)行Android。我們必須與許多編程語言合作凯正。
我們的無線網(wǎng)絡(luò)有些不可靠毙玻,我們有一些高延遲的環(huán)境。有些設(shè)備的功率比較低廊散,很多設(shè)備都是靠電池供電桑滩,資源比較匱乏。此外允睹,我們還要注意網(wǎng)絡(luò)帶寬的使用施符。
我們可以使用HTTP請求,并建立一個發(fā)布-訂閱模型來交換不同設(shè)備之間的數(shù)據(jù)擂找。然而戳吝,有一種協(xié)議是專門設(shè)計(jì)的,它比HTTP 1.1協(xié)議更輕巧贯涎,在涉及到不可靠的網(wǎng)絡(luò)和連接斷斷續(xù)續(xù)的情況下听哭,它能更好地工作。MQ Telemetry Transport( MQTT )更適合這種情況,在這種情況下陆盘,許多設(shè)備之間必須通過互聯(lián)網(wǎng)近乎實(shí)時地交換數(shù)據(jù)普筹,而我們需要消耗盡可能少的網(wǎng)絡(luò)帶寬。
MQTT協(xié)議是一種機(jī)器對機(jī)器(M2M Machine-to-Machine)及物聯(lián)網(wǎng)連接協(xié)議隘马。MQTT是一個輕量級的消息傳遞協(xié)議太防,它使用基于broker的發(fā)布訂閱機(jī)制。
了解MQTT協(xié)議的便捷場景
MQTT適用于以下需要進(jìn)行數(shù)據(jù)交換的應(yīng)用領(lǐng)域酸员。
- 資產(chǎn)跟蹤和管理
- 汽車遠(yuǎn)程信息處理技術(shù)
- 化學(xué)檢測
- 環(huán)境和交通監(jiān)測
- 野戰(zhàn)部隊(duì)自動化
- 火災(zāi)和氣體測試
- 家庭自動化
- 車載信息娛樂系統(tǒng) (IVI In-Vehicle Infotainment)
- 醫(yī)學(xué)
- 訊息傳遞
- 銷售點(diǎn)(POS Point of Sale)亭
- 鐵路
- 無線電頻率識別(RFID Radio-Frequency Identification)
- 監(jiān)視控制和數(shù)據(jù)采集(SCADA Supervisory Control and Data Acquisition)
- 老虎機(jī)
綜上所述蜒车,MQTT被設(shè)計(jì)成適合支持物聯(lián)網(wǎng)、M2M幔嗦、嵌入式和移動應(yīng)用中的以下典型挑戰(zhàn)酿愧。
- 輕量
- 以最小的數(shù)據(jù)包分發(fā)大量的數(shù)據(jù)。
- 支持面向事件的范式邀泉,異步雙向低延遲推送消息嬉挡。
- 輕松地將數(shù)據(jù)從一個客戶端發(fā)送至多個客戶端。
- 只要事件發(fā)生汇恤,就可以監(jiān)聽(面向事件的架構(gòu))庞钢。
- 支持一直連接和有時連接的模式。
- 在不可靠的網(wǎng)絡(luò)上發(fā)布信息因谎,并在脆弱的連接上提供可靠的傳輸基括。
- 與電池供電的設(shè)備或需要低功率消耗的設(shè)備配合得非常好。
- 能夠?qū)崿F(xiàn)近乎實(shí)時的信息傳遞蓝角。
- 數(shù)據(jù)安全和隱私
- 可擴(kuò)展亭枷,將數(shù)據(jù)分發(fā)到幾十萬個客戶龙巨。
使用發(fā)布-訂閱模式
在深入了解MQTT之前,我們必須先了解發(fā)布-訂閱模式遣总,也就是pub-sub模式昌抠。在publish-sub模式中患朱,發(fā)布消息的客戶端與接收消息的其他客戶端是解耦的〈渡唬客戶端不知道其他客戶端的存在裁厅。客戶端可以發(fā)布特定類型的消息侨艾,只有對特定類型的消息感興趣的客戶端才會收到發(fā)布的消息执虹。
發(fā)布-訂閱模式需要一個代理,也就是服務(wù)器唠梨。所有的客戶端都與broker建立連接袋励。通過broker發(fā)送消息的客戶端被稱為發(fā)布者。broker對接收到的消息進(jìn)行過濾,并將其分發(fā)到對接收到的消息類型感興趣的客戶端茬故。對特定類型的消息感興趣的客戶向經(jīng)紀(jì)人注冊的客戶被稱為訂閱者盖灸。因此,發(fā)布者和訂閱者都與經(jīng)紀(jì)人建立了聯(lián)系磺芭。
消息過濾的工作
broker必須確保訂閱者只收到他們感興趣的消息赁炎。在發(fā)布-訂閱模式中,可以根據(jù)不同的標(biāo)準(zhǔn)來過濾消息钾腺。我們將重點(diǎn)分析基于話題的過濾 徙垫,也稱為基于主題的過濾。
考慮到每條消息都屬于一個主題垮庐。當(dāng)發(fā)布者請求broker發(fā)布消息時松邪,必須同時指定主題和消息。經(jīng)紀(jì)人接收到消息后哨查,將其傳遞給所有訂閱了該消息所屬主題的訂閱者逗抑。
經(jīng)紀(jì)人不需要檢查消息的有效載荷就可以將消息傳遞給相應(yīng)的訂閱者,它只需要檢查每一條已經(jīng)到達(dá)并需要過濾的消息的主題寒亥,然后再發(fā)布給相應(yīng)的訂閱者邮府。
Raspberry Pi 3板子發(fā)布一條消息,以120英尺作為有效載荷溉奕,以sensor1/altitude作為主題褂傀。發(fā)布者,將發(fā)布請求發(fā)送給broker加勤。broker將消息分發(fā)到訂閱sensor1/altitude主題的兩個客戶端:iOS智能手機(jī)和Android平板電腦仙辟。
英特爾愛迪生板塊發(fā)布一條消息,以75 F作為有效載荷鳄梅,以sensor42/temperature作為主題叠国。發(fā)布者將發(fā)布請求發(fā)送給經(jīng)紀(jì)人。經(jīng)紀(jì)人將消息發(fā)布給唯一訂閱sensor42/temperature主題的客戶端:Android平板電腦戴尸。這樣粟焊,Android平板電腦就會收到兩條消息。
客戶端孙蒙、服務(wù)器和連接项棠。
MQTT broker被稱為MQTT服務(wù)器。MQTT客戶端可以同時是發(fā)布者和訂閱者挎峦,也就是說香追,客戶端可以向特定的主題發(fā)布消息,也可以接收屬于客戶端訂閱的主題的消息坦胶。
任何擁有TCP/IP協(xié)議棧并能夠使用MQTT庫的設(shè)備都可以成為MQTT客戶端翅阵,即成為發(fā)布者歪玲、訂閱者或既是發(fā)布者又是訂閱者。
有許多MQTT服務(wù)器可用于最流行的平臺掷匠,包括Linux滥崩、Windows和macOS。我們將使用Eclipse Mosquitto MQTT服務(wù)器(http://www.mosquitto.org)讹语。Mosquitto是一個開源的MQTT服務(wù)器钙皮,具有EPL/EDL許可證,與MQTT 5.0顽决、3.1和3.1.1版本兼容短条。其他服務(wù)器有Erlang MQTT Broker(EMQ),也就是EMQTT (http://www.emqtt.io)才菠,以及HiveMQ(http://hivemq.com)等茸时。此外有基于云的MQTT服務(wù)器合作,如CloudMQTT(http://www.cloudmqtt.com)赋访。
MQTT服務(wù)器是我們之前分析的發(fā)布/訂閱模型的中心樞紐可都。MQTT服務(wù)器負(fù)責(zé)對MQTT客戶端進(jìn)行認(rèn)證和授權(quán),客戶端經(jīng)過認(rèn)證和授權(quán)后就可以成為發(fā)布者和/或訂閱者蚓耽。所以渠牲,MQTT客戶端首先要做的就是與MQTT服務(wù)器建立連接。
為了建立連接步悠,MQTT客戶端必須向MQTT服務(wù)器發(fā)送一個CONNECT控制包签杈,該控制包的有效載荷必須包括所有必要的信息,以啟動連接并進(jìn)行認(rèn)證和授權(quán)鼎兽。MQTT服務(wù)器會檢查CONNECT包答姥,進(jìn)行認(rèn)證和授權(quán),并向客戶端發(fā)送一個CONNACK控制包的響應(yīng)谚咬,我們了解CONNECT控制包后再詳細(xì)分析鹦付。如果MQTT客戶端發(fā)送無效的CONNECT控制包,服務(wù)器會自動關(guān)閉連接序宦。
在MQTT客戶端和MQTT服務(wù)器之間建立了成功的連接后睁壁,服務(wù)器將保持連接的開放性背苦,直到客戶端失去連接或向服務(wù)器發(fā)送DISCONNECT控制包來關(guān)閉連接互捌。
CONNECT控制包必須在有效載荷中包含以下字段的值,以及控制包中包含的特殊標(biāo)志字節(jié)的位行剂。我們要了解這些字段和標(biāo)志的含義秕噪,因?yàn)楫?dāng)我們使用MQTT工具和MQTT客戶端庫時,我們將能夠指定它們的值厚宰。
ClientId : 客戶端標(biāo)識符腌巾,也稱為客戶端ID遂填,是一個字符串,用于標(biāo)識每個連接到MQTT服務(wù)器的MQTT客戶端澈蝙。每個連接到MQTT服務(wù)器的客戶端必須有一個唯一的ClientId吓坚,服務(wù)器使用它來標(biāo)識它所持有的與客戶端和服務(wù)器之間的MQTT會話有關(guān)的狀態(tài)。如果客戶端指定一個空值作為ClientId 灯荧,MQTT服務(wù)器必須生成一個唯一的ClientId來識別客戶端礁击。然而,這種行為取決于為CleanSession字段指定的值逗载。
CleanSession : 清潔會話標(biāo)志是一個布爾值哆窿,它指定了MQTT客戶端從MQTT服務(wù)器斷開連接后再重新連接的情況。如果CleanSession被設(shè)置為1或true厉斟,客戶端就會向MQTT服務(wù)器表明挚躯,只要網(wǎng)絡(luò)連接還在,會話就會持續(xù)擦秽。在MQTT客戶端斷開與MQTT服務(wù)器的連接后码荔,任何與該會話相關(guān)的信息都會被丟棄。從同一個MQTT客戶端到MQTT服務(wù)器的新連接將不會使用前一個會話的數(shù)據(jù)号涯,而是一個新的清潔會話目胡。如果CleanSession被設(shè)置為0或false,我們將使用一個持久的會話链快。在這種情況下誉己,MQTT服務(wù)器會存儲MQTT客戶端的所有訂閱,當(dāng)MQTT客戶端斷開連接時域蜗,MQTT服務(wù)器會存儲所有到達(dá)的消息巨双,這些消息具有特定的服務(wù)質(zhì)量級別,與MQTT客戶端在斷開連接時的訂閱相匹配霉祸。這樣一來筑累,當(dāng)同一個MQTT客戶端與MQTT服務(wù)器建立新的連接時,MQTT客戶端將擁有相同的訂閱丝蹭,并將接收到失去連接時無法接收的所有消息慢宗。我們將在后面深入探討消息的服務(wù)質(zhì)量等級以及它們與clean session標(biāo)志或persistent session選項(xiàng)的關(guān)系。
當(dāng)clean session標(biāo)志被設(shè)置為0或false時奔穿,客戶端向服務(wù)器表明它想要一個持久會話镜沽。我們只需要記住一個干凈的會話和一個持久的會話是相反的。
UserName : 如果客戶端想要指定一個用戶名來向MQTT服務(wù)器請求認(rèn)證和授權(quán)贱田,它必須將UserName標(biāo)志設(shè)置為1或true缅茉,并為UserName字段指定一個值。
password : 如果客戶端要指定密碼來請求 MQTT 服務(wù)器進(jìn)行身份驗(yàn)證和授權(quán)男摧,則必須將 Password 標(biāo)志設(shè)置為 1 或 true蔬墩,并為 Password 字段指定一個值译打。
ProtocolLevel : 協(xié)議級別值表示MQTT客戶端請求MQTT服務(wù)器使用的MQTT協(xié)議版本。
KeepAlive : KeepAlive是一個以秒為單位的時間間隔拇颅。如果keep alive的值不等于0奏司,MQTT客戶端會在KeepAlive指定的時間內(nèi)向服務(wù)器發(fā)送控制包。如果MQTT客戶端不需要發(fā)送任何控制包樟插,它必須向MQTT服務(wù)器發(fā)送一個PINGREQ控制包结澄,也就是一個ping請求來告訴MQTT服務(wù)器客戶端連接是活著的。MQTT服務(wù)器響應(yīng)PINGREQ控制包岸夯,向MQTT客戶端發(fā)出PINGRESP響應(yīng)麻献,即ping響應(yīng),告訴MQTT客戶端與MQTT服務(wù)器的連接是活的猜扮。當(dāng)沒有任何這些控制包時勉吻,連接就會被關(guān)閉。如果keep alive的值為0 旅赢,則關(guān)閉keep alive機(jī)制齿桃。
Will , WillQoS , WillRetain , WillTopic 和 WillMessage : 這些標(biāo)志和字段允許 MQTT 客戶端利用 MQTT 的遺囑功能。如果 MQTT 客戶端將 Will 標(biāo)志設(shè)置為 1 或 true煮盼,則表明它希望 MQTT 服務(wù)器存儲與會話相關(guān)聯(lián)的遺囑信息短纵。WillQoS標(biāo)志指定了最后一條WillMessage所需的服務(wù)質(zhì)量,WillRetain標(biāo)志則表示該messsage在發(fā)布時是否必須保留僵控。如果MQTT客戶端將Will標(biāo)志設(shè)置為1或true香到,它必須在WillTopic和WillMessage字段中指定WillMessage的主題和消息。如果MQTT客戶端斷開或失去與MQTT服務(wù)器的連接报破,MQTT服務(wù)器將把WillMessage字段中指定的消息發(fā)布到WillTopic字段中指定的主題悠就,并選擇服務(wù)質(zhì)量。我們將在后面詳細(xì)分析這個功能充易。
MQTT服務(wù)器將處理一個有效的CONNECT控制數(shù)據(jù)包梗脾,并將以CONNACK控制數(shù)據(jù)包作出響應(yīng)。這個控制包將包括以下標(biāo)志的值盹靴,包含在頭中炸茧。我們要了解這些標(biāo)志的含義,因?yàn)楫?dāng)我們使用MQTT工具和MQTT客戶端庫時稿静,我們將能夠檢索到它們的值梭冠。
SessionPresent : 如果MQTT服務(wù)器收到的連接請求的CleanSession標(biāo)志設(shè)置為1或true,那么SessionPresent標(biāo)志的值將為0或false自赔,因?yàn)闆]有存儲的會話將被重新使用妈嘹。如果在連接請求中CleanSession標(biāo)志被設(shè)置為0或false柳琢,那么MQTT服務(wù)器將使用一個持久會話绍妨,如果服務(wù)器在之前的連接中為客戶端設(shè)置了一個持久會話并將其找回润脸,那么SessionPresent標(biāo)志的值將為1或true。否則他去,SessionPresent將為0或false毙驯。想要使用持久化會話的MQTT客戶端可以使用這個標(biāo)志的值來決定它是否需要請求訂閱所需的主題,或者訂閱是否已經(jīng)從持久化會話中恢復(fù)灾测。
ReturnCode 爆价。如果授權(quán)和認(rèn)證通過,連接成功建立媳搪,ReturnCode的值將為0铭段。否則,返回代碼將不同于0秦爆,客戶端和服務(wù)器之間的網(wǎng)絡(luò)連接將被關(guān)閉序愚。下表顯示了ReturnCode的可能值及其含義。
返回碼的值
0 連接被接受
1 連接被拒絕等限,因?yàn)镸QTT服務(wù)器不支持MQTT客戶端在CONNECT控制包中要求的MQTT協(xié)議版本爸吮。
2 連接被拒絕,因?yàn)橹付ǖ腃lientId(客戶標(biāo)識符)已被拒絕望门。
3 連接被拒絕形娇,因?yàn)榫W(wǎng)絡(luò)連接已經(jīng)建立,但MQTT服務(wù)不可用筹误。
4 由于用戶名或密碼值不正確桐早,連接被拒絕。
5 由于授權(quán)失敗厨剪,連接被拒絕