发布与订阅
•
打个比方,你打电话给朋友,一直要等到朋友接电话了才能够开始交流,是一个典型的同步请求
/
应答的场景;而给一个好友邮件列表发电子邮件就不一样,你发好电子邮件该干嘛干嘛,好友到有空了去查看邮件就是了,是一个典型的一部发布
/
订阅的场景。
•
熟悉编程的同学一定非常熟悉这种设计模式了,因为它带来了这些好处:发布者与订阅者不用了解彼此,只要认识同一个消息代理即可。
•
发布者和订阅者不需要交互,发布者无需等待订阅者确认而导致锁定。
•
发布者和订阅者不需要同时在线,可以自由选择时间来消费消息。
主题
•
MQTT
是通过主题对消息进行分类的,本质上就是一个
UTF-d
字符串,不过可以通过反斜杠标识多个层级关系,主题并不需要创建,直接使用就可以。
•
主题还可以通过通配符进行过滤,其中层级数量没有限制不能包含任何的下文提到的特殊符号(
/
、
+
、
#
),必须至少包含一个字符
-
“
/A
”和“
A
”是不同的
-
“
A
”和“
A/
”是不同的
•
•
层级分隔符
/
•
只能匹配本级别不能匹配上级。例如,“
sport/+
”不匹配“
sport
”
•
多层通配符
#
•
单层通配符
+
•
一个
Subscribe
请求可以订阅多个
Topic
(节省带宽、多订阅尽量用一次请求)
服务质量-Qos0
对于qos0而言,对于client而言,有且仅发一次publish包,对于broker而言,有且仅发一次publish,简而言之,就是仅发一次包,是否收到完全不管,适合一些不是很重要的数据。
服务质量-Qos1
对于qos1而言,这个交互就是多了一次ack的作用,但是会有个问题,尽管我们可以通过确认来保证一定收到客户端或服务器的message,但是我们却不能保证message仅有一次,也就是当client没收到service的puback或者service没有收到client的puback,那么就会一直发送publisher。
流程:(publisher -> broker)
1.
publisher store msg -> publish ->broker
(传递
message
)
2.
broker ->
puback
-> publisher delete msg
(确认传递成功)
注意:
1.
publisher
必须保存
msg
,这样才能在重发
2.
publisher
如果在一定时间或
socket
断开等异常情况,会继续重发
msg
服务质量-Qos2
对于qos2可以实现仅仅接受一次message,其主要原理(对于publisher而言),
publisher和broker进行了缓存,其中publisher缓存了message和msgID,而broker缓存了msgID,两方都做记录所以可以保证消息不重复,但是由于记录是需要删除的,这个删除流程同样多了一倍
流程:(publisher -> broker)
1.
publisher store msg -> publish ->broker -> broker store
msgID
(传递
message
)
2.
broker ->
puberc
(确认传递成功)
3.
publisher ->
pubrel
-> broker delete
msgID
(告诉
broker
删除
msgID
)
4.
broker ->
pubcomp
-> publisher delete msg
(告诉
publisher
删除
msg
)
注意:
1.
第二步,即
puberc
不可以删除
publisher
的
msg
,因为第三步未必成功,这个时候就需要第一步提醒第二步继续发,而提醒必须要
msgID
遗嘱消息
•
MQTT本身是为信号不稳定的网络设计的,所有难免一些客户端会无故的和Broker断开连接。当客户端连接到Broker时,可以指定LWT,Broker回定期检测客户端是否有异常。当客户端异常掉线时,Broker就往连接时指定的Topic里面推送当时指定的LWT消息。
•
当客户端断开连接时,发送给相关的订阅者的遗嘱消息。以下情况回发送Will Message:
•
服务端发生了I/O错误或者网络失败;
•
客户端在定义的心跳时期失联;
•
客户端在发送下线包之前关闭网络连接;
•
服务端在收到下线包之前关闭网络连接;
遗嘱消息---使用场景
在客户端 A 进行连接时候,遗嘱消息设定为”offline“,客户端 B 订阅这个遗嘱主题。 当 A 异常断开时,客户端 B 会收到这个”offline“的遗嘱消息,从而知道客户端 A 离线了。
遗嘱消息---高级使用场景
高级使用场景 这里介绍一下如何将 Retained 消息与Will 消息结合起来进行使用。
客户端 A 遗嘱消息设定为”offline“,该遗嘱主题与一个普通发送状态的主题设定成同一个 A/status;
当客户端 A 连接时,向主题 A/status 发送 “online” 的 Retained 消息,其它客户端订阅主题 A/status的时候,获取 Retained 消息为 “online” ; 当客户端 A 异常断开时,系统自动向主题 A/status 发送”offline“的消息,其它订阅了此主题的客户端会马上收到”offline“消息;如果遗嘱消息被设定了 Retained 的话,这时有新的订阅A/status主题的客户端上线的时候,获取到的消息为“offline”。