初步认识mqtt

发布时间:2026/10/16 8:42:16

初步认识mqtt 什么是MQTTMQTTMessage Queuing Telemetry Transport消息队列遥测传输协议是一种基于发布/订阅publish/subscribe模式的轻量级通讯协议该协议构建于TCP/IP协议上可以以极少的代码和有限的带宽为连接远程设备提供实时可靠的消息服务。服务质量qos0“至多一次”消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。1“至少一次”确保消息到达但消息重复可能会发生。2“只有一次”确保消息到达一次。在一些要求比较严格的计费系统中可以使用此级别。MQTT 发布/订阅架构MQTT 采用发布/订阅Publish/Subscribe模式消息的流转由三个核心角色协作完成。下面这张流程图展示了 Publisher、Broker 与 Subscriber 之间的关系以及消息从发布到分发的完整路径发布消息到主题按主题分发按主题分发按主题分发Publisher 发布者Broker 消息代理Subscriber 订阅者 ASubscriber 订阅者 BSubscriber 订阅者 C各角色职责说明Publisher发布者负责向 Broker 发布消息并指定消息所属的主题Topic。发布者无需关心有哪些订阅者也无需知道订阅者的地址只需将消息交给 Broker 即可。Broker消息代理是整个架构的中枢负责接收发布者发来的消息并根据主题匹配规则将消息分发给所有订阅了该主题的客户端。Broker 还承担会话管理、QoS 保障、离线消息缓存等职责。Subscriber订阅者向 Broker 订阅感兴趣的主题当该主题有新消息到达时Broker 会主动推送给订阅者。一个主题可以被多个订阅者同时订阅从而实现一对多的消息广播。MQTT与HTTP/WebSocket对比对比维度MQTTHTTPWebSocket通信模式发布/订阅一对多请求/响应一对一全双工点对点协议开销极低报文头最小仅 2 字节较高每次请求都携带大量头部信息较低握手后头部开销小实时性高服务端主动推送毫秒级延迟低需客户端轮询存在延迟高双向实时推送适用场景物联网、传感器、移动端低功耗通信传统 Web 页面、RESTful API实时聊天、在线协作、股票行情简要说明MQTT 采用发布/订阅模式天然支持一对多广播且报文头极小、省电省带宽非常适合资源受限的物联网设备HTTP 是经典的请求/响应模型每次通信都要重建连接与头部信息实时性依赖轮询适合普通 Web 接口WebSocket 在握手后建立长连接双向实时推送能力强但连接管理相对复杂适合需要高频双向交互的场景。示例代码publicclassMqttClientTest{publicstaticvoidmain(String[]args)throwsMqttException{MqttClientclientnewMqttClient(tcp://127.0.0.1:1883,client,newMemoryPersistence());MqttConnectOptionsoptionsnewMqttConnectOptions();options.setUserName(admin);options.setPassword(qwer0103.toCharArray());// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录// 这里设置为true表示每次连接到服务器都以新的身份连接options.setCleanSession(true);// 设置超时时间 单位为秒options.setConnectionTimeout(10);// 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线但这个方法并没有重连的机制options.setKeepAliveInterval(20);// 连接client.connect(options);// 订阅client.subscribe(test);client.setCallback(newMqttCallback(){OverridepublicvoidconnectionLost(Throwablethrowable){System.out.println(connection success .....);}OverridepublicvoidmessageArrived(Strings,MqttMessagemqttMessage)throwsException{System.out.println(topic is s,Message is mqttMessage.toString());}OverridepublicvoiddeliveryComplete(IMqttDeliveryTokeniMqttDeliveryToken){}});// 创建消息MqttMessagemessagenewMqttMessage(hello World!.getBytes());// 设置消息的服务质量// 最多一次(0) 至少一次(1) 恰好一次(2)message.setQos(2);// 发布消息client.publish(test,message);// 断开连接client.disconnect();// 关闭客户端client.close();}}断线重连与自动订阅恢复在实际物联网场景中网络波动是常态客户端与 Broker 之间的连接随时可能中断。为保证消息不丢失、业务不中断我们需要在connectionLost回调中实现自动重连并在重连成功后重新订阅之前订阅的主题。publicclassMqttReconnectClient{// 重连间隔单位毫秒这里设置为 5 秒privatestaticfinallongRECONNECT_INTERVAL5000L;// 最大重连次数-1 表示无限重连privatestaticfinalintMAX_RECONNECT_TIMES-1;privateMqttClientclient;privateMqttConnectOptionsoptions;// 需要恢复订阅的主题privateString[]topics{test};publicvoidconnect()throwsMqttException{clientnewMqttClient(tcp://127.0.0.1:1883,reconnect-client,newMemoryPersistence());optionsnewMqttConnectOptions();options.setUserName(admin);options.setPassword(qwer0103.toCharArray());// 设置是否清空 session// 若设置为 falseBroker 会保留客户端的会话与离线消息// 重连后无需重新订阅即可恢复之前的订阅关系// 若设置为 true每次连接都以全新身份接入重连后必须手动重新订阅。options.setCleanSession(false);options.setConnectionTimeout(10);options.setKeepAliveInterval(20);// 设置自动重连Broker 断开后由客户端自动尝试重连options.setAutomaticReconnect(true);client.setCallback(newMqttCallback(){OverridepublicvoidconnectionLost(Throwablethrowable){System.out.println(连接丢失throwable.getMessage());// 手动重连逻辑按固定间隔重试直到成功reconnect();}OverridepublicvoidmessageArrived(Stringtopic,MqttMessagemessage)throwsException{System.out.println(topic is topic,Message is message.toString());}OverridepublicvoiddeliveryComplete(IMqttDeliveryTokentoken){}});client.connect(options);// 首次连接成功后订阅主题subscribeTopics();}/** * 手动重连循环尝试直到连接成功或达到最大次数 */privatevoidreconnect(){intattempt0;while(MAX_RECONNECT_TIMES-1||attemptMAX_RECONNECT_TIMES){attempt;try{Thread.sleep(RECONNECT_INTERVAL);if(!client.isConnected()){client.connect(options);}// 重连成功后恢复订阅subscribeTopics();System.out.println(重连成功已恢复订阅);break;}catch(Exceptione){System.out.println(第 attempt 次重连失败e.getMessage());}}}/** * 订阅主题首次连接与重连成功后都会调用 */privatevoidsubscribeTopics()throwsMqttException{client.subscribe(topics);}}重连与 session 恢复策略说明重连间隔示例中设置为 5 秒RECONNECT_INTERVAL避免网络抖动时频繁重连给 Broker 造成压力。实际生产环境可根据业务容忍度调整通常建议 3~10 秒。session 恢复setCleanSession(false)是关键。Broker 会持久化客户端的会话状态包括订阅关系和离线期间的消息QoS 1/2重连后无需重新订阅即可自动恢复若使用setCleanSession(true)则每次重连都必须手动重新订阅且离线消息会丢失。自动重连 vs 手动重连setAutomaticReconnect(true)由客户端 SDK 内置机制处理重连但重连成功后不会自动恢复订阅因此仍需在connectionLost中配合手动重连或重连成功后的订阅恢复逻辑确保订阅关系不丢失。常见问题与排查在实际接入 MQTT 的过程中除了断线重连还会遇到一些典型的连接与消息问题。下面列出 3 个最常见的问题并给出原因分析与对应的解决代码片段。问题 1连接被 Broker 拒绝用户名/密码错误原因分析Broker 开启了认证校验客户端传入的用户名或密码与 Broker 配置不一致导致连接握手阶段被拒绝抛出MqttSecurityException或连接返回码为 5连接被拒绝用户名或密码错误。解决代码连接前先校验配置并捕获认证异常给出明确提示。MqttConnectOptionsoptionsnewMqttConnectOptions();options.setUserName(admin);options.setPassword(qwer0103.toCharArray());options.setConnectionTimeout(10);try{client.connect(options);System.out.println(连接成功);}catch(MqttSecurityExceptione){// 认证失败检查用户名/密码是否与 Broker 配置一致System.err.println(认证失败请检查用户名或密码e.getMessage());}catch(MqttExceptione){// 其他连接异常检查 Broker 地址、端口、网络连通性System.err.println(连接异常返回码e.getReasonCode()原因e.getMessage());}问题 2订阅后收不到消息主题通配符不匹配原因分析订阅主题与发布主题不匹配。MQTT 主题支持通配符匹配单层、#匹配多层。若订阅使用sensor//temp而发布到sensor/room1/humidity则因层级不匹配而收不到消息此外#必须位于主题末尾。解决代码订阅前先确认主题层级必要时用通配符覆盖多个层级。// 订阅单层通配匹配 sensor/room1/temp、sensor/room2/tempclient.subscribe(sensor//temp);// 订阅多层通配匹配 sensor/ 下所有主题client.subscribe(sensor/#);// 精确订阅只匹配 sensor/room1/tempclient.subscribe(sensor/room1/temp);问题 3重连后消息丢失cleanSession 设置不当原因分析setCleanSession(true)时Broker 不保留客户端会话断线期间的离线消息QoS 1/2会被丢弃重连后也无法恢复订阅关系导致消息丢失。若业务要求断线期间消息不丢必须使用setCleanSession(false)并配合 QoS 1/2。解决代码使用持久会话并设置合理的 QoS。MqttConnectOptionsoptionsnewMqttConnectOptions();// 持久会话Broker 保留订阅关系与离线消息options.setCleanSession(false);// 设置自动重连断线后由 SDK 自动恢复连接options.setAutomaticReconnect(true);client.connect(options);// 使用 QoS 1 或 2 订阅确保离线消息被 Broker 缓存client.subscribe(sensor/#,1);排查建议若仍收不到离线消息可检查 Broker 是否开启了持久会话支持以及客户端是否在断线后及时重连离线时间过长Broker 可能清理会话。
延伸阅读

更多相关文章

2026/10/16 8:42:16

从CDH到Cloudera Manager:企业级Hadoop大数据平台部署全流程指南

1. 为什么是CDH:平台选型的底层逻辑1.1 不是只有CDH一个选择先说说我个人的结论:如果你的团队从零开始搭大数据平台,CDH(Cloudera Distribution including Apache Hadoop)依然是一条稳妥、省事、可控的路。很多第一次接…

2026/10/16 8:42:16

教育信息化与AI、计算机科学融合发展的实践路径探析

近两年我陆续参与了好几个教育信息化相关的项目,一个最直观的感受是:很多学校在硬件和平台上的投入已经不小了,但教学形态的改变却远没跟上。电子白板换了、录播教室建了、教务系统也上了云,可大多数课堂还是"新瓶装旧酒&quo…

2026/10/16 8:42:15

用UpTrain构建生成式AI应用评测体系,让模型表现可量化

上线一个带大模型功能的业务系统,最让人头疼的不是写代码,而是“上线之后怎么判断模型到底行不行”。用户反馈“回答得不对”“引用的资料是错的”“有时候老是答非所问”,开发同学翻遍日志也只能看到响应时间、token 消耗和 HTTP 状态码&…

2026/10/16 11:04:41

BUUCTF PWN进阶:格式化字符串、栈迁移与ret2csu实战解析

刷 BUUCTF 的 PWN 题,从 41 到 45 这几道题给我的感觉是:前 40 题还在练手速,栈溢出让你把ret地址改了基本就能拿 shell;到了这个阶段,题目开始正经考“你懂不懂底层到底发生了什么”。格式化字符串怎么泄露地址、栈空…

2026/10/16 11:04:41

CLion源码编译OpenCV:构建可调试可追踪的开发闭环

1. 这不是“配环境”,而是构建一个可调试、可追踪、可复现的OpenCV开发闭环很多人点开这篇标题,第一反应是:“哦,又一个CLion配OpenCV的教程”。但我要先泼一盆冷水:如果你只是想把cv::imread跑起来,那大可…

2026/10/16 11:04:41

操作系统隔离与系统调用全链路:从用户态到内核态的穿越

6.S081这门操作系统课程讲到第三讲,终于开始触及最核心的部分:OS organization和system calls。前面几讲我们在用户态这边打转,fork、exec、wait这些系统调用用得很熟,但很少认真想过一个问题——你随手调一个write(),…

2026/10/16 11:04:41

多智能体协作新范式:DeepSeek Harness集成Codex与Claude Code实战

一眼看到这次更新的标题,我先是愣了一下——把 Codex、Claude Code 直接做成官方插件,这不再是"自己改造工具链"的玩法,而是把多个编程代理放进同一个调度框架里当子智能体用。我前阵子刚把一批并行任务从单代理切到多代理协作&…

2026/10/16 11:04:41

Netty带宽饱和下的连接处理:背压、水线与实战调优

刚经历了一次让人印象深刻的线上事故:某推送网关在业务高峰期整体带宽吃到接近上限,单个连接的数据还能正常处理,但新连接进来之后要么握手阶段超时,要么连进来以后迟迟拿不到响应。更诡异的是,已经建立的长连接里&…

2026/10/16 10:54:16

ConvLSTM实战:伦敦空气质量时空预测全流程解析

1. 问题定义与模型选型:为什么偏偏是ConvLSTM上一篇我们完成了伦敦地区空气质量数据的获取和预处理。拿到了20多个监测站点的逐小时污染物浓度记录,做了缺失值插补,也看了基本的时间分布规律。但数据准备好了并不代表能直接进入训练&#xff…

2026/10/16 5:33:43

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/16 4:03:48

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/16 0:01:11

Cephadm实战指南:Linux系统工程师的生产级Ceph集群部署与排障

简介:本资源是一份完整的Ceph分布式存储系统中文技术文档合集,面向Linux系统运维工程师、云平台架构师及存储方向开发者,帮助读者系统掌握Ceph集群的部署、配置与运维核心能力。文档覆盖对象存储(RGW)、块设备&#xf…

2026/10/16 0:01:11

ITK中SpatialObject几何体系解析:坐标系、变换与管道集成

1. 空间对象的定位:为什么 ITK 需要一套几何描述体系很多刚开始接触 ITK 的朋友,包括我自己,最初都是被它的图像滤波、配准、分割这些“正统”功能吸引进来的。等真正上手做点实际项目,比如把分割出来的器官边界做量化分析、给血管…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑