2. MQTT核心概念:发布/订阅模型深度解析

各位同学,咱们今天聊点实在的。MQTT 最核心的东西,就是它的发布/订阅模型。我第一次接触这个模型时,说实话有点懵——跟传统的客户端/服务器模式完全不一样。但搞懂了之后,你会发现它简直是为物联网量身定做的。

2.1 发布/订阅模型:到底怎么玩?

传统的 HTTP 通信,就像你打电话——必须两边都在线,还得知道对方的号码。MQTT 的发布/订阅模型呢?更像是一个微信群。

  • 发布者(Publisher):只管往群里发消息,不用管谁在看
  • 订阅者(Subscriber):只接收自己感兴趣的话题,不用管谁发的
  • 代理(Broker):就是那个群主,负责转发消息

我在一个智能家居项目里用过这套机制。温度传感器只管往 "house/temperature" 这个主题发数据,空调、手机 App、智能音箱各自订阅自己需要的主题。各干各的,互不干扰。你想想看,如果每个设备都要互相知道对方的 IP 地址,那得多麻烦?

核心要点:发布者和订阅者完全解耦。它们不需要知道对方的存在,不需要同时在线,甚至不需要在同一网段。这就是 MQTT 最大的魅力。

2.2 主题(Topic)与通配符:消息的路由规则

主题就是消息的标签。MQTT 的主题用 "/" 分层,有点像文件路径。我个人习惯用这种结构:

设备类型/位置/传感器类型/动作
例如:sensor/kitchen/temperature/report

为什么这么设计?因为配合通配符,能实现非常灵活的消息过滤。

两种通配符

通配符 含义 示例 匹配结果
+ 匹配单层 sensor/+/temperature 匹配 sensor/kitchen/temperature、sensor/bedroom/temperature
# 匹配多层 sensor/# 匹配 sensor/ 下的所有主题

我的经验:通配符别滥用。我曾经在一个项目里看到有人用 "#" 订阅所有主题,结果 broker 负载直接飙到 90%。订阅范围越精确,系统性能越好。

2.3 服务质量(QoS 0/1/2)原理:消息到底能不能丢?

QoS 是 MQTT 里最容易让人迷糊的地方。说白了,就是你在「效率」和「可靠性」之间做个取舍。

QoS 0:最多发一次

发出去就不管了。像扔纸飞机——飞不飞到随缘。适合传感器定期上报的温度数据,丢一两个无所谓。

QoS 1:至少发一次

保证消息能到,但可能重复。像快递员给你打电话说「快递到了」,你没听到,他过会儿再打一次。你可能会接到两个电话,但至少不会错过。

QoS 2:恰好发一次

最严格,也最慢。通过四次握手保证消息不丢不重。适合控制指令,比如「打开阀门」——重复执行一次可能出事故。

避坑指南:我曾经在一个项目里把所有消息都设成 QoS 2,结果设备一多,broker 直接卡死。后来改成:控制指令用 QoS 2,状态上报用 QoS 1,日志数据用 QoS 0。系统瞬间就稳了。

2.4 会话(Clean Session)与遗嘱消息(Will Message)

这两个概念,说白了就是解决「设备掉线了怎么办」的问题。

Clean Session:要不要记住我?

  • Clean Session = true:每次连接都是全新的,之前的订阅和离线消息全部清空。适合手机 App 这种临时设备。
  • Clean Session = false:broker 会记住你的订阅和离线消息。设备重连后,能收到掉线期间的消息。适合传感器这种长期在线的设备。

嗯,这里要注意:持久会话会占用 broker 内存。我见过有人给 10 万个设备都开了持久会话,结果 broker 内存爆了。合理规划很重要。

遗嘱消息:最后的遗言

遗嘱消息是 MQTT 里一个很巧妙的设计。设备连接时可以设置一条遗嘱消息,当设备异常断开时,broker 会帮它把这条消息发出去。

举个例子:

// 设备连接时设置遗嘱
client.connect({
  will: {
    topic: 'device/status',
    payload: 'offline',
    qos: 1,
    retain: true
  }
});

// 正常运行时定时发送心跳
client.publish('device/status', 'online', { qos: 1, retain: true });

这样,其他设备订阅了 "device/status" 主题,就能实时知道这个设备是在线还是离线了。

我的建议:遗嘱消息的 QoS 至少设成 1。设成 QoS 0 的话,遗嘱消息本身也可能丢,那就失去意义了。

小结

发布/订阅模型让设备之间解耦,主题和通配符让消息路由灵活,QoS 让你在效率和可靠性之间做选择,会话和遗嘱消息处理了设备掉线的各种场景。这些概念搞懂了,MQTT 你就掌握了 80%。

下一章咱们聊 MQTT 的连接流程和心跳机制,那才是真正动手写代码的地方。