家好,我是明说网络的小明同学。今天我们来聊一聊物联网通协议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小时内与您取得联系。