邊緣與雲端協議
協議概述
- 本節首先解釋了為何在 HTTP 之外,還需要其他協議來跨廣域網路 (WAN) 傳輸數據。
- HTTP 在物聯網中的角色:
- HTTP 雖然為網際網路提供服務超過 20 年,但其客戶端/伺服器模式設計主要用於通用計算。
- 物聯網設備通常受到資源限制(如遠程、頻寬),因此需要更高效、安全和可擴展的協議。
- 儘管如此,HTTP 在物聯網和邊緣系統中仍有其用途,特別是 HTTP/2 和 HTTP/3 協議相對高效。
- 透過 TLS 的安全性在 HTTP 會話中也很常見,且 HTTP 無處不在,常用于各種通信和 RESTful API。
- TCP 與 UDP:
- 在數據通信中,TCP 和 UDP 協議是基礎選擇。
- TCP 的實現比 UDP 更複雜,但提供穩定性和可靠性。
- UDP 不具備 TCP 的穩定性和可靠性,因此一些設計需要在 UDP 之上的應用層增加彈性來補償。
- UDP 用於某些物聯網通信協議,如 NB-IoT。
- 消息導向中間件 (Message-Oriented Middleware, MOM):
- MOM 的基本思想是兩個設備之間使用分布式消息佇列進行通信。
- MOM 將消息從一個用戶空間應用程序傳遞給另一個。
- 一些設備生產數據加入佇列,而另一些則使用佇列中的數據。
- 某些 MOM 實現需要代理或中間人作為中心服務,生產者和消費者與代理有發布和訂閱類型的關係。
- AMQP、MQTT 和 STOMP 都是 MOM 實現,其他還有 CORBA 和 Java 消息傳遞服務。
- 使用佇列的 MOM 實現可以提高設計的彈性,數據即使伺服器發生故障也能持久化。
- RESTful 模型:
- MOM 實現的替代方案是 RESTful。
- 在 RESTful 模型中,伺服器擁有資源的狀態,但狀態不會在消息中從客戶端傳輸到伺服器。
- RESTful 設計使用 HTTP 方法(如 GET、PUT、POST 和 DELETE)將請求放置在資源的統一資源識別符 (URI) 上。
- 此架構中不需要代理或中間代理,且基於 HTTP 堆棧,享有 HTTPS 等大多數服務。
- RESTful 設計是典型的客戶端–伺服器架構,客戶端透過同步請求–響應模式啟動對資源的訪問。
- URI 用作基於 Web 的數據流量的識別符,最著名的是統一資源定位符 (URL)。URI 可以分解為多個部分:
- 在 RESTful 設計中,即使伺服器出現故障,客戶端也要負責。
- 圖 10-1 比較了 MOM 服務(基於 MQTT,使用中間代理伺服器、發布者和訂閱者)與 RESTful 服務(基於 HTTP,客戶端到伺服器通信)。
MQTT (Message Queue Telemetry Transport)
- MQTT 是一個非常輕量級的發布/訂閱協議,專為受限設備和低頻寬、高延遲或不可靠的網路設計。
- 歷史與目標:
- 起源於 IBM 的 WebSphere Message Queue 技術,於 1999 年由 Andy Stanford-Clark 和 Arlen Niper 為解決透過衛星連接遠程油氣管道的特殊限制而創建。
- 目標是:
- 實現簡單
- 提供服務質量
- 非常輕量級和頻寬高效
- 數據不可知
- 持續會話意識
- 解決安全問題
- MQTT 於 2010 年 3.1 版作為免版稅產品發布,2013 年被納入 OASIS 聯盟並於 2014 年發布 3.1.1 版本,也成為 ISO 標準 (ISO/IEC PRF 20922)。
- 表 10-1 說明了 OASIS MQTT 標準的功能發布和 HiveMQ 發布的時間線。
- MQTT 5 的改進:
- MQTT 5 (2019 年發布) 解決了 MQTT 3.1.1 在定制/添加元數據和跨不同供應商平台、庫、數據路徑互操作性方面的問題。
- 引入了 用戶屬性 (User Properties),允許使用自定義鍵值對或將屬性嵌入報頭中,模仿 HTTP 和 AMQP 的元數據攜帶能力。
- 這大大提高了互操作性,允許不同供應商傳達數據格式和用途,代理可以據此執行操作。
- 引入了 AUTH 數據包類型,可在連接建立後用於複雜的挑戰/響應認證序列,例如 Kerberos 和 OAuth。
- 修改了 返回碼 (Reason Codes),包括來自所有響應消息的否定確認,使客戶端能更好地了解失敗原因並改進錯誤報告。
- 引入了 會話過期計時器 (Session Expiry Interval) 和 cleanStart 字段,簡化了會話處理,默認所有 MQTT 5 會話都是持久的。
- MQTT 發布–訂閱模型 (Pub/Sub):
- 它將發送消息的客戶端(發布者)與接收消息的客戶端(訂閱者)分離。
- MQTT 本質上不是消息佇列,因為它通常不存儲消息。如果沒有訂閱者,消息就會被忽略和丟失。
- 保留消息 (Retained Message) 是一個特殊情況,它是一個單個消息實例,被保存以供未來解析,並會發送給任何新的訂閱者。
- MQTT 代理 (Broker) 是核心,負責連接客戶端和過濾數據。
- 圖 10-2 展示了 MQTT 發布–訂閱模型和拓撲,其中客戶端在邊緣運行,發布和/或訂閱由 MQTT 代理管理的主題。
- 發布者/訂閱者模型的一個注意事項是,發布者和訂閱者在啟動傳輸前都必須知道主題分支和數據格式。
- MQTT 成功地將發布者與消費者分離,且由於代理的存在,無需直接識別發布者和消費者。
- MQTT 和其他發布/訂閱模型是時不變的,消息可以被訂閱者隨時讀取和響應。
- 該模型具備良好的擴展性,雲端管理的 MQTT 代理每小時可接收數百萬條消息,支持成千上萬的發布者。
- MQTT 與數據格式無關,有效負載 (payload) 中可以包含任何類型數據(文本、圖像、音頻、加密、二進制、JSON 等),但 JSON 和二進制數據最常見。
- 允許的最大數據包大小為 256 MB,但雲和代理可能會有較小的限制(如 IBM Watson 128 KB,Google 256 KB)。
- MQTT 5 共享訂閱 (Shared Subscriptions):
- 允許多個客戶端共享同一訂閱
- 並在訂閱組中以循環方式接收消息,實現負載平衡。
- 圖 10-3 說明了這一功能。
- MQTT 5 主題別名 (Topic Aliases):允許用整數值替換冗長的主題名稱,解決大規模可擴展性問題,尤其針對頻繁發布小消息的設備。
- MQTT 架構細節:
- MQTT 基於 TCP,因此包含數據包可靠傳輸的保證。
- 它是一個非對稱協議,意味著只需要一方(例如,客戶端)使用協議即可通信。
- 保留消息 (Retained Message):代理可無限期保留消息,並立即傳送給訂閱該主題的新客戶端,使新客戶端無需等待即可獲取狀態。
- 遺囑 (Last Will and Testament, LWT):客戶端在連接階段指定的消息。
- 如果客戶端不正常斷開連接(如保活超時、I/O 錯誤),代理會將 LWT 消息廣播給所有其他訂閱客戶端。
- 保活機制 (Keep-alive system):為補救無線傳感器環境中可能出現的半開啟會話狀態(伺服器認為連接仍可靠但無數據傳輸),MQTT 使用保活系統。
- 客戶端和代理定期發送 PINGREQ/PINGRESP 數據包以確認連接有效。
- 持久連接 (Persistent connections):允許 MQTT 在代理端保存客戶端的所有訂閱、未確認的 QoS 消息和客戶端丟失的所有新 QoS 消息,減少重新建立連接的開銷。
- 該信息由 client_id 參數引用。
- MQTT 5 的 cleanStart 字段簡化了會話處理,所有 MQTT 5 會話默認都是持久的。
- 服務質量 (Quality of Service, QoS):MQTT 定義了三個級別的 QoS:
- QoS-0(至多一次):最底層,類似“即發即棄”,無接收者確認或發送者重試。
- 適用於不需要消息佇列、有線連接或嚴格頻寬限制的場景。
- QoS-1(至少一次):保證消息至少傳遞給接收方一次,接收方會用 PUBACK 響應確認。
- 應作為默認用法,比 QoS-2 快得多,降低傳輸成本。
- QoS-2(僅一次):最高層級,確保並通知發送方和接收方消息已正確發送,透過多步握手(PUBREC, PUBREL, PUBCOMP)產生更多流量。
- 用於關鍵任務應用,以及重複消息重傳可能導致故障的情況。
- 並非所有 MQTT 實現都支持所有 QoS 值(如 QoS-2 常被排除)。
- MQTT 5 改變了 QoS-1 和 QoS-2 消息的行為:如果 TCP 連接正常,代理和客戶端可能不會重傳 MQTT 消息,只有在 TCP 會話關閉時才重發未確認數據包。
- MQTT 狀態轉換:
- 會話透過 CONNECT 消息開始,透過 DISCONNECT 消息正確終止。
- MQTT 3.1.1 與 MQTT 5 在狀態轉換和遺囑消息處理上有所不同。
- MQTT 5 引入了會話過期計時器,若客戶端在特定時間內未連接,會話將被丟棄,減少了客戶端負擔。
- 這個新的狀態轉換過程稱為 Clean Start。
- 圖 10-4 比較了 MQTT 3.1.1 和 MQTT 5 的狀態轉換。
- MQTT 數據包結構:
- MQTT 數據包位於 OSI 模型網路棧的 TCP 層之上。
- 包含 2 字節的固定報頭(必須存在)、可變大小的報頭(可選)和有效負載(可選)。
- MQTT 5 引入了 屬性 (Properties) 的概念,以克服 MQTT 3.1.1 在可擴展性、定制性和互操作性方面的弱點。
- MQTT 數據類型:
- MQTT 支持多種數據類型,MQTT 5 支持 7 種:
- 比特
- 雙字節整數
- 四字節整數
- UTF-8 編碼字符串
- 可變字節整數
- 二進制數據
- UTF-8 字符串對(僅限 MQTT 5)。
- 表 10-2 展示了各種數據類型格式。
- MQTT 通信格式:
- 通信鏈接始於客戶端向代理發送 CONNECT 消息,只有客戶端可以啟動會話,且不能直接與另一個客戶端通信。
- CONNECT 消息(表 10-3):
- clientID
- 遺囑
- QoS
- 用戶名
- 密碼
- 保活時間
- MQTT 5 中用戶名和密碼字段都是可選的,可獨立使用。
- CONNACK 消息(表 10-4):代理對 CONNECT 消息的響應,包含響應碼。
- PUBLISH 消息(表 10-5):客戶端將數據發布到主題分支,每條消息包含主題、有效負載等。
- SUBSCRIBE 消息(表 10-6):訂閱數據包的有效負載包括主題 ID 和 QoS 級別。
- 通配符 (Wildcards):
- +:替換主題字符串名稱中的單個級別(例如,“美國/+/密爾沃基”)。
- #:替換多個級別,必須是主題名稱中的最後一個字符(例如,“美國/威斯康星州/#”)。
- $SYS:MQTT 代理的特殊統計模式,客戶端不能發布到此主題。
- MQTT 3.1.1 工作範例:
- 以 Google Cloud Platform (GCP) 作為 MQTT 3.1.1 的接收器和攝取器為例。
- GCP 要求 MQTT 之上的強加密 (TLS),並使用 JSON Web Token (JWT) 和證書代理加密所有數據包。
- 範例使用 paho.mqtt.client Python 庫,設定回調函數,並使用 JWT 進行身份驗證,然後向訂閱主題發布簡單字符串。
MQTT-SN (MQTT for Sensor Networks)
- MQTT 的衍生協議,專為傳感器環境中典型的無線個人區域網路設計,支持低頻寬鏈路、鏈路故障、短消息長度和資源受限的硬體。
- 特性:
- 非常輕量級,可以在 BLE 和 Zigbee 上成功運行。
- 不需要 TCP/IP 堆棧,可在串行鏈路(首選)或 UDP 上使用。
- 架構與拓撲:
- 包含四個基本組件(圖 10-6):
- 網關 (Gateway):負責 MQTT-SN 到 MQTT 的協議轉換。
- 轉發器 (Forwarder):在傳感器和 MQTT-SN 網關之間轉發 MQTT-SN 幀。
- 客戶端 (Client):行為與 MQTT 相同,能訂閱和發布數據。
- 代理 (Broker):行為與 MQTT 相同。
- 網關類型:
- 透明網關 (Transparent Gateway):管理多個獨立的 MQTT-SN 流,並將每個流轉換為 MQTT 消息,與 MQTT-SN 連接和 MQTT 到代理的連接具有一對一的關係。
- 聚合網關 (Aggregating Gateway):將多個 MQTT-SN 流合併為發送給雲 MQTT 代理的少量 MQTT 流,減少通信開銷和並發連接數,設計上更複雜。需要客戶端發布或訂閱相同的主題才能實現功能。
- 網關廣播與發現:
- 網關首先綁定到 MQTT 代理,然後向連接的客戶端或其他網關發出 ADVERTISE 數據包。
- 客戶端只能連接到單個網關,但會存儲活動網關列表。
- 新消息類型:
- ADVERTISE(定期廣播)
- SEARCHGW:客戶端搜索特定網關,包含:
- radius 參數
- GWINFO(網關對 SEARCHGW 的響應,包含網關 ID 和地址)
- MQTT 與 MQTT-SN 的區別:
- MQTT-SN 不如 MQTT 流行。
- MQTT-SN 有三個 CONNECT 消息,而 MQTT 只有一個,多的兩個用於顯式傳輸遺囑主題和遺囑消息。
- MQTT-SN 可在簡化的介質和 UDP 上運行。
- MQTT-SN 中 MQTT 主題名稱被短的雙字節主題 ID 消息替換,以緩解無線網路頻寬限制。
- 可在 MQTT-SN 中使用預定義的主題 ID 和簡短的主題名稱,無需註冊。
- MQTT-SN 引入了發現過程,幫助客戶端查找伺服器和網關的網路地址。
- MQTT-SN 中的 cleanSession 擴展到遺囑功能,遺囑數據也被保存。
- MQTT-SN 使用經修訂的 keepAlive 過程,支持休眠客戶端,伺服器或邊緣路由器會緩衝發給客戶端的消息,並在喚醒時發送。
- 選擇 MQTT 代理:
- 表 10-7 展示了在構建 MQTT 解決方案時選擇商業和開源代理時需注意的要點和當前(撰寫本書時)特徵
- 例如是否支持集群
- 持久化
- 認證
- 授權
- 網橋
- 規則引擎
- 高可用性等。
CoAP (Constrained Application Protocol)
- CoAP 是 IETF (RFC7228) 的產物,專門用於約束設備的通信協議。
- 它最初為邊緣節點之間的 M2M 通信量身定制,並支持透過代理映射到 HTTP。
- 特性與優勢:
- 提供類似 HTTP 的簡單資源結構,但對資源和頻寬要求極低。
- Colitti 等人的研究證明 CoAP 相對於標準 HTTP 的效率更高。
- 在類似硬體上,CoAP 的一些實現比 HTTP 等效器性能好 64 倍(表 10-8)。
- 架構細節:
- 基於模仿和替代 HTTP 功能的概念,但更輕量級。它不能完全取代 HTTP,因為它確實缺乏 HTTP 強大系統所需的特性。
- 主要特性:類似 HTTP、無連接協議
- 安全性透過 DTLS 而非 TLS 保證
- 異步消息交換、輕量設計和資源要求
- 較低的報頭開銷
- 支持 URI 和內容類型
- 基於 UDP 而非 TCP/UDP
- 允許代理橋接到 HTTP 會話的無狀態 HTTP 映射
- 兩個基本層:
- 請求/響應層 (Request/Response Layer):負責發送和接收基於 RESTful 的查詢,請求以 CON 或 NON 消息為載體,響應以 ACK 消息為載體。
- 消息層 (Messaging Layer):使用四種基本消息類型之一處理終端之間的單個消息交換,支持多播和擁塞控制。
- 圖 10-8 對比了 HTTP 堆棧與 CoAP 堆棧。
- CoAP 與 HTTP 共享其上下文、語法和用法,尋址方式也類似於 HTTP URI 結構,使用 GET、PUT、POST、DELETE 等請求。響應碼也模仿 HTTP(如 2.01: Created, 4.04: Not Found)。
- 典型 URI 形式:coap://example.com:5683/path。
- 七個主要參與者:
- 端點
- 代理(正向、反向、交叉)
- 客戶端
- 伺服器
- 中介
- 源伺服器和觀察者 (Observer)
- 觀察者在 CoAP 中是獨特的,允許設備監測特定資源的更改,類似於 MQTT 訂閱模型。
- 圖 10-9 展示了 CoAP 架構示例,說明了 CoAP 客戶端可相互通信或與雲服務通信,也可透過代理橋接到 HTTP 服務。
- CoAP 利用端口 5683 進行資源發現,DTLS 啟用時使用端口 5684。
- CoAP 消息格式:
- 基於 UDP 傳輸,可能不可靠,因此引入兩種不同消息類型來補償可靠性問題。
- 四種消息類型:
- 可確認消息 (Confirmable, CON):需要 ACK。
- 如果未收到 ACK,發送方會以指數增長的間隔重發 CON 消息,直到收到 ACK 或 RST,這是 CoAP 的擁塞控制形式。
- 不可確認消息 (Non-Confirmable, NON):不需要 ACK,本質上是“即發即棄”或廣播消息。
- 確認消息 (Acknowledgment, ACK):確認 CON 消息,可附帶其他數據。
- 重置消息 (Reset, RST):指示已收到 CON 消息但上下文丟失,可附帶其他數據。
- CoAP 是一個 RESTful 設計,請求/響應消息附帶在 CoAP 消息上,實現更高效率和頻寬保留。
- 圖 10-10 展示了 CON 和 NON 消息傳遞示例。
- 圖 10-12 展示了 CoAP 重傳機制,發送方負責管理超時並重傳至最大重傳次數。
- CoAP 包含一個簡單的緩存模型,透過消息頭中的響應碼控制。
- Max_Age 選項用於控制緩存元素的壽命和數據的新鮮度,默認為 60 秒,最大可達 136.1 年。
- 代理在緩存中發揮作用。
- 例如,休眠的邊緣傳感器可以使用代理緩存數據以節省電源。
- CoAP 消息頭設計獨特,實現最大效率和頻寬節省。
- 報頭長度為四個字節,典型的請求消息只需要 10~20 字節的頭,通常是 HTTP 頭的 1/10。
- 圖 10-13 展示了 CoAP 消息結構。
- 重複消息 (Duplicate messages):UDP 可能導致 CON 和 NON 傳輸的重複消息,CoAP 規範規定接收方應對收到的每個重複消息進行 ACK,但只處理一個請求或響應。
- 觀察者 (Observer):允許客戶端註冊觀察,每當被監視的資源更改狀態時,伺服器將通知客戶端。
- 圖 10-14 展示了 CoAP 觀察者註冊和更新過程。
- CoAP 標準中沒有固有的身份驗證或加密,用戶必須依賴 DTLS 提供這種安全級別 (coaps://)。
- 提供資源發現機制:向 /.well-known/core 發送 GET 請求即可披露設備上已知資源列表,也可使用查詢字符串過濾。
- CoAP 使用範例:
- 使用基於 Python 的 aiocoap 庫,展示了客戶端使用 PUT 將溫度廣播到已知 URI 的實現,以及伺服器實現 PUT 和 GET 方法的服務。
其他協議
- 本節探討了一些特定用例的替代方案,儘管 MQTT 和 CoAP 是目前最流行的物聯網協議。
- STOMP (Simple Text Oriented Messaging Protocol):
- Codehaus 設計的一種基於文本的協議,用於使用面向消息的中間件進行操作。
- 與 HTTP 有相似之處,並透過 TCP 進行操作。
- 由幀頭和幀體組成,目前規範是 STOMP 1.2。
- 優化於人類可讀性、容錯解析和自描述數據。
- 在網路和通信協議上效率低下(不是其預期設計目標)。
- 不適用於連接有限、通信服務收費高或基於電池的電源受限設備。
- MOM 協議,具有應用程序定義的消息結構,發布者和訂閱者的消息結構是鎖定的,這在大規模部署中可能導致問題。
- 與本章提出的許多協議不同,它不直接處理訂閱主題或佇列,而是使用類似 HTTP 的語義(如帶有目標字符串的 SEND),代理必須解析消息並映射到客戶端的主題或佇列。
- AMQP (Advanced Message Queuing Protocol):
- 一個經過強化和驗證的 MOM 協議,由摩根大通於 2003 年設計,並於 2011 年合併到 OASIS 小組,已由 ISO 和 IEM 標準化 (ISO/IEC 1964:2014)。
- 在銀行和信貸交易行業廣泛使用,也在物聯網中佔有一席之地。
- 位於 TCP 棧頂,使用端口 5672 進行通信。
- 流量控制、消息導向的通信系統,是線級協議和低級接口。
- 試圖將發布者與訂閱者脫鉤,與 MQTT 不同,它具有負載均衡和正式排隊的機制。
- AMQP 部署的網路拓撲結構是中心輻射型的,具有中樞相互通信的能力。
- 消息幀透過單向鏈路在節點之間移動。
- 如果消息透過節點傳遞且未轉換,全局識別符不變,否則分配新 ID。
- 三種消息傳遞模式:
- 點對點 (Point-to-point)
- 發布/訂閱 (Publish/Subscribe)
- 消息中繼 (Message relay)。
- 圖 10-15 展示了典型的 AMQP 架構拓撲,包含:
- 生產者
- 消費者
- 代理
- 交換服務(直接、扇出、主題交換)
- 佇列
- 提供了使用 Python 結合 Rabbit MQ 和 Pika 庫的範例。