家好,我是明說網絡的小明同學。今天我們來聊一聊物聯網通協議MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議)。
故事的開頭,我們從MQ(Message Queue)說起。
什么是MQ
MQ,Message queue,消息隊列,就是指保存消息的一個容器。
消息隊列最原始的模型:生產者先將消息投遞一個叫做「隊列」的容器中,然后再從這個容器中取出消息,最后再轉發給消費者。如下圖所示:
那么問題來了,那么為什么生產者不直接將消息發送給消費者呢?好處在哪里呢?
消息隊列有什么優勢呢?
如下圖所示,本身串行的訂單,會員,消息,推薦系統在MQ的加持下,變成了并行,系統和系統之間只依賴于MQ,而不依賴于各類系統。
參考:https://www.zhihu.com/question/54152397
其實,MQ在其中起到了以緩沖的作用。
MQ 解決的最核心的問題:系統解耦(系統之間不相互依賴)和異步(流程不再串行):
從MQ的角度去理解MQTT
而MQTT是專門針對物聯網設計的消息隊列!實際上使用的是MQ其中的發布/訂閱模式
訂閱什么意思呢?舉個例子,訂報紙。設想一個場景:你從報亭A訂閱了“人民日報”,那么一旦報亭有了"人民日報”,就會給你發一份。其實,這個“人民日報”在MQTT中就是topic的角色。
如果熟悉設計模式的同學,一定會聯想到觀察者模式,簡直是異曲同工之妙啊。
觀察者模式:當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。比如,當一個對象被修改時,則會自動通知依賴它的對象。觀察者模式屬于行為型模式。
觀察者模式 | 菜鳥教程
MQ與MQTT的區別
名稱 | 解釋 |
mqtt | 一種通信協議,類似人類交談中的漢語、英語、俄語中的一種語言規范 |
MQ | 一種通信通道,也叫消息隊列,類似人類交談中的用電話、email、微信的一種通信方式 |
以上為MQ的背景,下面進入正題。
MQTT簡介
隨著 5G 時代的來臨,萬物互聯的偉大構想正在成為現實。海量的設備接入和設備管理對網絡帶寬、通信協議以及平臺服務架構都帶來了很大挑戰。尤其對于物聯網設備來說,電量消耗,資源控制等都尤為重要。在此背景下MQTT應運而生。
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基于發布/訂閱(publish/subscribe)模式的"輕量級"通訊協議,該協議構建于TCP/IP協議上,由IBM在1999年發布(由 IBM 的 Andy Stanford-Clark 和 Arcom 的 Arlen Nipper 為了一個通過衛星網絡連接輸油管道的項目開發,之后 IBM 一直將 MQTT 作為一個內部協議在其產品中使用,直到 2010 年,IBM 公開發布了 MQTT 3.1 版本。在 2014 年,MQTT 協議正式成為了 OASIS(結構化信息標準促進組織)的標準協議,來源)。
MQTT最大優點在于,可以以極少的代碼和有限的帶寬,為連接遠程設備提供實時可靠的消息服務。作為一種低開銷、低帶寬占用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。MQTT 3 (當前版本3.1.1)是目前使用的最為廣泛的 MQTT 協議標準。
為什么選擇MQTT
它的設計思想是輕巧、開放、簡單、規范,易于實現。這些特點使得它對很多場景來說都是很好的選擇,特別是對于受限的環境如機器與機器的通信(M2M)以及物聯網環境(IoT)。
MQTT的應用場景
MQTT 協議廣泛應用于物聯網、移動互聯網、智能硬件、車聯網、電力、能源等領域。
相關參考資料
https://www.emqx.cn/mqtt
https://www.runoob.com/w3cnote/mqtt-intro.html
https://www.jianshu.com/p/ecde412d2eeb
MQTT協議中文版,https://mcxiaoke.gitbooks.io/mqtt-cn/content/
https://zhuanlan.zhihu.com/p/158145940
MQTT通信模型
有別于傳統的客戶端/服務器通訊協議,MQTT協議并不是端到端的,消息傳遞通過代理,包括會話(session)也不是建立在發布者和訂閱者之間,而是建立在端和代理之間。代理解除了發布者和訂閱者之間的耦合。這對理解MQTT很重要
通過下面兩個圖理解MQTT(不愧是MQ)
MQTT中的角色
在MQTT中,有三個主要的角色:
角色 | 解釋 | 類比 |
發布者(Publish) | 可以是一個應用程序或一臺設備 | 類似于報紙發布者 |
代理(Broker)(服務器) | MQTT服務器以稱為"消息代理"(Broker),可以是一個應用程序或一臺設備。它是位于消息發布者和訂閱者之間 | 類似于以前的報刊亭,會有很多人向報亭發布報紙,報停會更具不同的訂閱分發報紙。 |
訂閱者(Subscribe) | 可以是一個應用程序或一臺設備 | 類似于報紙訂閱者 |
需要注意的是,這里的發布者和訂閱者并不是絕對的。發布者可以變成訂閱者,訂閱者也可以變成發布者,甚至是同一臺設備既可以是發布者也可以是訂閱者,甚至是broker。
這是與現實中報亭的例子有些區別的地方,人們可以訂報紙,同時還能發報紙,甚至是自己給自己賣報紙!
消息
這三個角色之間通過消息進行通信:MQTT傳輸的消息分為:主題(Topic)和負載(payload)兩部分:
mosquitto使用
Mosquitto是一個實現了MQTT3.1協議的代理服務器,由MQTT協議創始人之一的Andy Stanford-Clark開發
學習網址:
libmosquitto編程:https://blog.csdn.net/dancer__sky/article/details/77855249
MQTT的學習之Mosquitto安裝&使用
MQTT服務端軟件使用:https://zhuanlan.zhihu.com/p/56727359
安全
MQTT安全篇:為何以及如何運用MQTT提供的安全特性來保證物聯網項目的順利實施 https://zhuanlan.zhihu.com/p/21421094
篇文章,我們聊聊 Redis 的高級特性之一: 發布訂閱。
Redis 發布訂閱 (pub/sub) 是一種消息通信模式:發送者 (pub) 發送消息,訂閱者 (sub) 接收消息。
圖中,消費者1和消費者2 訂閱了 Redis 服務的頻道 channel ,當生產者通過 PUBLISH 命令發送給頻道 channel 時, 這個消息就會被發送給訂閱它的兩個客戶端。
下表列出了 Redis 發布訂閱常用命令:
命令 | 用法 | 描述 |
PSUBSCRIBE | PSUBSCRIBE pattern [pattern ...] | 訂閱一個或多個符合給定模式的頻道 |
PUBSUB | PUBSUB subcommand [argument [argument ...]] | 查看訂閱與發布系統狀態 |
PUBLISH | PUBLISH channel message | 將信息發送到指定的頻道 |
PUNSUBSCRIBE | PUNSUBSCRIBE [pattern [pattern ...]] | 退訂所有給定模式的頻道 |
SUBSCRIBE | SUBSCRIBE channel [channel ...] | 訂閱給定的一個或多個頻道的信息 |
UNSUBSCRIBE | UNSUBSCRIBE [channel [channel ...]] | 指退訂給定的頻道 |
我們開啟兩個 redis-cli 客戶端,演示了發布訂閱是如何工作的。
客戶端 A 執行訂閱命令:
subscribe mychannel
訂閱命令執行成功后:
客戶端 B 執行發布命令:
publish mychannel helloworld
發布命令執行成功后,客戶端 A 就會接收到新的消息:
每個 Redis 服務器進程都維持著一個表示服務器狀態的 redis.h/redisServer 結構, 結構的 pubsub_channels 屬性是一個字典, 這個字典就用于保存訂閱頻道的信息:
struct redisServer {
// ...
dict *pubsub_channels;
// ...
};
其中,字典的鍵為正在被訂閱的頻道, 而字典的值則是一個鏈表, 鏈表中保存了所有訂閱這個頻道的客戶端。
下圖中, client2 、 client5 和 client1 就訂閱了 channel1 , 而其他頻道也分別被別的客戶端所訂閱:
當客戶端調用 SUBSCRIBE 命令時, 程序就將客戶端和要訂閱的頻道在 pubsub_channels 字典中關聯起來。
舉個例子,如果客戶端 client10086 執行命令 SUBSCRIBE channel1 channel2 channel3 ,那么前面展示的 pubsub_channels 將變成下面這個樣子:
當調用 PUBLISH channel message 命令, 程序首先根據 channel 定位到字典的鍵, 然后將信息發送給字典值鏈表中的所有客戶端。
如果某個客戶端執行命令 PUBLISH channel1 "hello moto" ,那么 client2 、 client5 和 client1 三個客戶端都將接收到 "hello moto" 信息:
在使用發布訂閱功能時,需要理解兩點。
1、保證先讓消費者先訂閱隊列,然后再讓生產者發布消息。
如果消費者異常掛掉并重新上線,它只能接收新的消息。在其下線期間,生產者發布的消息將無法被消費者接收,因為找不到該消費者,這些消息會被丟棄。
如果所有消費者都下線,那么生產者發布的消息將因為沒有任何消費者而全部被丟棄。
2、發布訂閱不具備數據持久化的能力
發布訂閱相關的操作不會被寫入到 Redis 數據庫(RDB)或追加寫入文件(AOF)中。如果 Redis 宕機并重新啟動,Pub/Sub 的數據將會全部丟失。
基于上面的分析,發布訂閱功能特別適合對少量消息丟失不敏感的通知類型的場景
筆者開源了一個短信服務,為了提升系統性能,應用信息存儲在本地內存中,定時任務會每隔30秒重新刷新一次緩存,但在分布式部署的場景下,不同應用間的數據可能沒有及時同步。
我們可以使用 Redis 的發布訂閱功能,實現本地內存的及時刷新。
1、配置 Redis 頻道監聽器容器
2、觸發發布消息
當應用發送變化時,比如新增、修改、刪除,則調用發送消息到頻道方法。
下圖,當我們啟動兩個應用,修改應用信息時,我們發現兩個應用的本地內存都發生變化了。
參考資料:
https://redisbook.readthedocs.io/en/latest/feature/pubsub.html
022年9月19日,海關總署發布2022年第88號(關于調整進口貨物報關單申報要求的)公告,調整《中華人民共和國海關進口貨物報關單》和《中華人民共和國海關進境貨物備案清單》有關項目的填報要求。
1、新增“已實施預防性消毒”申報項目,該項目為勾選項,包括“是”和“否”兩個選項,進口貨物境內收貨人或其報關單代理人如已開展“預防性消毒”則選擇“是”,否則選擇“否”。
【注】:根據《新冠肺炎疫情期間現場消毒評價標準》(WS/T 774-2021)規定:“預防性消毒為在沒有明確的傳染源存在時,對可能受到病原微生物污染的場所和物品進行的消毒。”
2、實際進境貨物必須填報“已實施預防性消毒”和“啟運日期”。
公告原文鏈接:http://www.customs.gov.cn/customs/302249/2480148/4590561/index.html
【關聯解讀】:
? 對滿足監管要求的進口非冷鏈物品,在申報進口貨物報關單時,必須填報“啟運日期”和“已實施預防性消毒”兩個字段。
? 該公告內容的調整不免讓我們聯想到2022年9月7號單一窗口的更新 :“貨物申報系統新增進口非冷鏈貨物高污染風險通知功能”,即對于海關綜合研判為存在被新冠病毒污染高風險的進口非冷鏈貨物,貨物申報系統通過首頁通知、高污染風險通知查詢、狀態查詢、訂閱推送等功能及時告知企業。
?綜合來看,上述的調整與2022年7月12日,國務院應對新型冠狀病毒肺炎疫情聯防聯控機制綜合組發布的國衛明電[2022]270號(關于進一步優化進口物品新冠肺炎疫情防控工作的通知)的內容息息相關。下面,讓小編帶著大家一起回顧一下關于進口非冷鏈物品的相關內容。
① 其中“裝載入境物品的航空器、船舶、列車、汽車自離開啟運口岸起超過24小時的進口非冷鏈物品”與本公告的“啟運日期”關聯起來。
② “已實施預防性消毒的進口非冷鏈物品”是不是也與“預防性消毒”關聯起來啦。
【小Tips】:
進口貨物報關單的這一小調整是不是讓大家也有些迷茫呢。但還是應該注意“如實申報”哦,進口貨物收貨人或其報關代理人都需要額外關注哦,如果對于這兩個字段的解讀不確定的,可以試著咨詢相關海關哦。
資訊來源:公眾號德正木材物流
*請認真填寫需求信息,我們會在24小時內與您取得聯系。