首先先了解一下底层的协议:
1. MQTT
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅 (publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。 MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作 为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应 用。
由于物联网的环境是非常特别的,所以MQTT遵循以下设计原则:
(1)精简,不添加可有可无的功能;
(2)发布/订阅(Pub/Sub)模式,方便消息在传感器之间传递,解耦Client/Server模式,带来的 好处在于不必预先知道对方的存在(ip/port),不必同时运行;
(3)允许用户动态创建主题(不需要预先创建主题),零运维成本;
(4)把传输量降到最低以提高传输效率;
(5)把低带宽、高延迟、不稳定的网络等因素考虑在内;
(6)支持连续的会话保持和控制(心跳);
(7)理解客户端计算能力可能很低;
(8)提供服务质量( quality of service level:QoS)管理
(9)不强求传输数据的类型与格式,保持灵活性(指的是应用层业务数据)
2. MQTT协议实现方式:
MQTT传输的消息分为:主题(Topic)和负载(payload)两部分:
**(1)Topic,**可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容 (payload);
**(2)payload,**可以理解为消息的内容,是指订阅者具体要使用的内容。
3. Qos: 消息服务质量(Quality of Service)
MQTT 设计了 3 个 QoS 等级。
理解: Qos: 规定自己想要发出,或者接收到的消息的规则
- QoS 0:消息最多传递一次,如果当时客户端不可用,则会丢失该消息。
“至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。
这一级别可用于如下情况
,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方 式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就 收不到了。
- QoS 1:消息传递至少 1 次。
“至少一次”,确保消息到达,但消息重复可能会发生
- QoS 2:消息仅传送一次。
“只有一次”,确保消息到达一次。在一些要求比较严格的计费系统中,可以使用此级别。在计费 系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的 APP的推送,确保用户收到且只会收到一次
MQTT 发布与订阅操作中的 QoS 代表了不同的含义:
发布时的 QoS 表示消息发送到服务端时使用的 QoS
订阅时的 QoS 表示服务端向自己转发消息时可以使用的最大 QoS。
基本都是用QoS2
MQTT 发布与订阅操作中的 QoS 代表了不同的含义,发布时的 QoS 表示消息发送到服务端时使用的 QoS,订阅时的 QoS 表示服务端向自己转发消息时可以使用的最大 QoS。
- 当客户端 A 的发布 QoS 大于客户端 B 的订阅 QoS 时,服务端向客户端 B 转发消息时使用的 QoS 为客户端 B 的订阅 QoS。
- 当客户端 A 的发布 QoS 小于客户端 B 的订阅 QoS 时,服务端向客户端 B 转发消息时使用的 QoS 为客户端 A 的发布 QoS。
总结: 也就是说QoS这个东西的设置是对消息的接收来做保证的,即如果是
QoS 1 我只负责发一次,收得到收不到我不管. 当网络状态不稳定的时候就会出现丢失现象
QoS 2 是能够保证至少收到一次,但是存在重复消费的问题.
QoS 3 保证只有一条信息到达
* 如果发布和订阅的客户端服务质量等级不相同时,谁的低按谁的为准
4. Topic通配符匹配规则
- 层级分隔符 /
/ 用来分割主题树的每一层,并给主题空间提供分等级的结构。当两个通配符在一个主题中出现的 时候,主题层次分隔符的使用是很重要的。
示例:
love/you/with/all/my/heart
- 多层通配符 #
多层通配符有可以表示大于等于0的层次。因此,love/#也可匹配到单独的love,此时#代表0 层。
多层通配符一定要是主题树的最后一个字符。比如说,love/#是有效的,但是love/#/with是无效 的。
- 单层通配符 +
只匹配主题的一层
1. love/you/+ :匹配love/you/with和love/you/and,但是不匹配
love/you/with/all/my/heart。
2. 单层通配符只匹配1层,love/+不匹配love。
3. 单层通配符可以被用于主题树的任意层级,连带多层通配符。它必须被用在主题层级分隔符/的右边,除非它是指定自己。因此,+和love/+都是有效的,但是love+无效。单层通配符可以用在主题树的末端,也可以用在中间。比如说,love/+和love/+/with都是有效。
通配符注意事项:
1.主题层次分隔符被用来在主题中引入层次。多层的通配符和单层通配符可以被使用,但他们不能被使用来做发布者的消息。
2.Topic命名尽量见名知意,符合规范,主题名字是大小写敏感的。比如说,love和LOVE是两个不同的主题。
3.以/开头会产生一个不同的主题。比如说,/love与love不同。/love匹配"+/+"和/+,但不匹配+
4.不要在任何主题中包含null(Unicode \x0000)字符。
5.在主题树中,长度被限制于64k内但是在这以内没有限制层级的数目 。
6.可以有任意数目的根节点;也就是说,可以有任意数目的主题树。
1.EMQ X
EMQ X 是开源社区中最流行的 MQTT 消息服务器。
Windows安装emqx_windows emqx安装_罗小爬EX的博客-CSDN博客
优点:
单机能支持百万的 MQTT 连接;集群能支持千 万级别的 MQTT 连接;
支持丰富的物联网协议,包括 MQTT、MQTT-SN、CoAP、 LwM2M、LoRaWAN 和 WebSocket 等;
2. Dashboard(可视化界面)
EMQ X 提供了 Dashboard 以方便用户管理设备与监控相关指标。通过 Dashboard可以查看服务器基本 信息、负载情况和统计数据,可以查看某个客户端的连接状态等信息甚至断开其连接,也可以动态加载 和卸载指定插件。除此之外,EMQ X Dashboard 还提供了规则引擎的可视化操作界面,同时集成了一 个简易的 MQTT 客户端工具供用户测试使用。
3. MQTTX
模拟客户端
MQTTX:跨平台 MQTT 5.0 桌面客户端工具
MQTT X 是 EMQ 开源的一款优雅的跨平台 MQTT 5.0 桌面客户端,它支持 macOS, Linux, Windows。 MQTT X 的 UI 采用了聊天界面形式,简化了页面操作逻辑,用户可以快速创建连接,允许保存多个客 户端,方便用户快速测试 MQTT/MQTTS 连接,及 MQTT 消息的订阅和发布。
发送消息
这里一定要记住是在哪方加前缀
1. 消息延迟发布
此功能由 emqx_mod_delayed 模块提供,需要开启模块后才能使用此功能。
$delayed/{DelayInteval}/{TopicName} 单位: S
当客户端使 用特殊主题前缀 $delayed/{DelayInteval} 发布消息到 EMQ X 时,将触发延迟发布功能
示例:
$delayed/15/x/y : 15 秒后将 MQTT 消息发布到主题 x/y 。
$delayed/60/a/b : 1 分钟后将 MQTT 消息发布到 a/b
示例: 在MQTT X上演示
现在在MQTTX
上模拟四个客户端: 洗衣机
,空调
,电视机
,手机
现在让洗衣机
,空调
,电视机
订阅phoneMessage
这个主题, 消息服务质量设置为2
,以后都设置为2
各个实例订阅的主题和发送的主题如下:
洗衣机客户端订阅主题: phoneMessage
空调客户端订阅主题: phoneMessage
电视机客户端订阅主题: phoneMessage
手机发送的主题: $delayed/2/phoneMessage // 2 秒后发送到订阅phoneMessage的客户端
在手机客户端上发送消息: 注意此时特殊主题的前缀在发布者上
两秒后,其他订阅这个主题的客户端都收到了消息.
2. 共享订阅
注意注意注意: 🚩
共享订阅的主题格式是针对订阅端来指定的,例如: $share/group1/cookie ;而消息的发布方是向主 题: cookie 发布消息。这样在订阅方才能达到负载均衡的效果。
共享订阅是在多个订阅者之间实现负载均衡的订阅方式:
EMQ X 支持两种格式的共享订阅前缀:
示例 | 前缀 | 真实主题名 | |
---|---|---|---|
方式一(不带群组的共享订阅) | $queue/name/cookie | $queue/ | name/cookie |
方式二(带群组的共享订阅) | $share/group1/cookie | $share/group1/ | cookie |
应用场景:
1. 对于方式一不带群组的共享订阅:
在我们取钱完成时,我们要求需要向当前用户的手机发送一条短信, 为了提高服务的容错性,我们准备了多台发短信的服务, 但是我们要求只发送一条短信,此时我们就可以使用 方式一, 使只有一台机器收到发送短信的消息如下, 只会有一台机器收到
各个实例订阅的主题和发送的主题如下:
消息服务实例1订阅的主题: $queue/cookie
消息服务实例2订阅的主题: $queue/cookie
消息服务实例3订阅的主题: $queue/cookie
发布者发布的主题: cookie
2. 对于方式二带群组的共享订阅:
$share/group1/cookie
带分组的使用的特殊前缀是: $share/{group}/{TopicName}
使用场景如下:
在方式一的上面做一点点更改, 就是在发布者消息发送成功后, 不仅仅需要有一台消息服务实例去发送消息, 也需要有一台邮件服务实例去发送邮件. 所以这里就可以进行分组
message 组 : 消息服务实例1 消息服务实例2 消息服务实例2
email组: 邮件服务实例1 邮件服务实例2
各个实例订阅的主题和发送的主题如下:
(message组)
消息服务实例1 $share/message/cookie
消息服务实例2 $share/message/cookie
消息服务实例2 $share/message/cookie
(email组)
邮件服务实例1 $share/email/cookie
邮件服务实例2 $share/email/cookie
发布者实例 cookie
此时就可以保证两个组中都会有一个实例服务收到消息.
3. 负载均衡策略修改默认 随机
在EMQ X 服务的 etc/emqx.conf中修改
broker.shared_subscription_strategy = random
负载均衡策略 | 描述 |
---|---|
random | 在所有订阅中随机选择 |
round_robin | 按照订阅顺序轮询 |
sticky | 一直发往上次选取的订阅者 |
hash | 按照发布者ClientID的哈希值 |
后面还有代理订阅,保留消息,认证,ACL,这里暂时还没有用到所以就不在记录, 用到的话再补充
具体的实现马上补充