目录
一 主题订阅
MQTT主题(topic)由一或多个斜杠分割的层级组成。eg:level1/level2/level3/data(建议避免斜杠开头)
订阅/发布 前无需提前创建
主题命名规范:
- 至少包含一个字符。
- 可以输入空格
- 大小写敏感,注意区分。
- “/” 是一个有效的主题,可用于表示广泛的主题或用作同时订阅多个主题的通配符。
多主题订阅(主题通配符):
- 单层级通配符:+ (替换单个主题层级) eg:level1/+/level3/data
- 多层级通配符:# (必须放在主题字符的最后,且只能有一个) eg:level1/#
以$符号开头的主题有专门的目的。用于MQTT代理(broker)的内部统计信息,请勿订阅及禁止发布
二 多个客户端订阅
普通订阅:每发布一条消息,每个订阅的客户端都会收到该消息副本
共享订阅:发布在该topic的消息只会生成一个消费副本,投递给其中一个客户端。
共享订阅组:想共享订阅同一topic的客户端集合
如何使用:
1.无需修改客户端,只需要订阅时订阅共享订阅主题即可。
2.指定共享订阅的负载均衡算法:修改emqx服务的配置etc/emqx.conf
##设置共享订阅的分发策略
broker.shared_subscription_strategy = random (或round_robin, sticky, hash)
##开启或关闭共享订阅对于 qos1/qos2 消息的 ACK 检查功能。开启后,如果投递到某个订阅者但收不到ACK,将尝试投递给订阅组里的下一个订阅者。
broker.shared_dispatch_ack_enabled = true
共享订阅主题:遵循该命名规范的主题 $share/{Share Name}/{Topic Filter}
释义:
$share 固定前缀
{Share Name} 表示当前共享订阅使用的共享名 即Group Name 共享订阅组名
{Topic Filter} 我们实际想要订阅的主题
{Share Name}/{Topic Filter} 才唯一地标识一个共享订阅组
共享订阅和普通订阅互不影响,当某个消息同时与共享订阅和普通订阅匹配时,服务端会向每个匹配的普通订阅的客户端发送该消息的副本,同时向每个匹配的共享订阅组中的其中一个会话发送该消息的副本
共享订阅的核心在于服务端如何在客户端之间分配消息负载。比较常见的负载均衡策略有以下几种:
随机(Random),在共享订阅组内随机选择一个会话发送消息。
轮询(Round Robin),在共享订阅组内按顺序选择一个会话发送消息,循环往复。
哈希(Hash),基于某个字段的哈希结果来分配。
粘性(Sticky),在共享订阅组内随机选择一个会话发送消息,此后保持这一选择,直到该会话结束再重复这一过程。
本地优先(Local),随机选择,但优先选择与消息的发布者处于同一节点的会话,如果不存在这样的会话,则退化为普通的随机策略。
三 QoS(Quality of Service 服务质量)
QoS等级 是消息可靠性核心保障手段,分为0(最多一次)、1(至少一次)和2(正好一次)
QoS 0 会消息丢失
QoS 1 会消息重复
QoS 2 既可以保证消息到达,也可以保证消息不会重复,但传输成本最高。QoS 2 能够达到的吞吐一般仅为 QoS 0、1 的一半左右
四 消息重复
场景:发送方未收到接收方的 PUBACK 报文,重新发送消息
解决:在QoS 2中,设计了一套复杂的握手机制来防止消息的重复。该过程包括四种类型的控制报文:PUBLISH、PUBREC、PUBREL和PUBCOMP。首先,发送方发送含有消息的PUBLISH报文并等待PUBREC,接收PUBREC后,发送方发出PUBREL并等待PUBCOMP。当PUBCOMP被接收方收到后,双方均可确认消息只被成功接收一次。
五 消息丢失
QoS 0 消息最主要的丢失场景:TCP连接关闭、重置,有可能丢失消息。
解决:QoS 1要求消息至少传递一次,发送端存储消息直到从接收端收到 PUBACK 回执,在没有收到回执时会重新发送
六 消息顺序
MQTT并不保证消息的绝对顺序性。消息在发布者和订阅者之间传递时,可能会因为网络延迟或其他因素而导致乱序。只能通过业务手段来保证顺序。
使用QoS1或QoS2等级的消息传输时,即使网络不稳定导致重发,MQTT协议也确保了最终消息的处理顺序。这是因为,每条消息都会被分配一个唯一的标识符,该标诈符会在消息送达过程中携带,以此来保证消息传输的顺序性。同理,可在消息中使用时间或递增版本来控制顺序
七 遗嘱消息LWT(Last Will and Testament)
遗嘱消息的用途主要包括:
状态通知: 客户端可以设置遗嘱消息来通知其他设备或应用程序自己的状态变化,例如设备离线状态。
清理资源: 遗嘱消息也可用于清理资源,例如释放某些保留的状态或资源。
在客户端建立连接时,可以指定一个遗嘱消息及其相关的主题。如果客户端由于网络故障或其他原因非正常断开连接,遗嘱消息将由服务器自动发布。