Eclipse Mosquitto 2.0.22 发布详解:Broker、客户端库与动态安全插件的关键修复
后端消息队列消息路由【免费下载链接】mosquittoEclipse Mosquitto - An open source MQTT broker项目地址https://gitcode.com/gh_mirrors/mos/mosquitto点击查看免费下载Eclipse Mosquitto 于 2025 年 7 月发布 2.0.22 版本这是一次聚焦稳定性的 bugfix 发布发布说明原文见 version-2-0-22-released.md。本次修复横跨 Broker 核心、桥接Bridge、MQTT v5 保活机制、WebSocket、动态安全插件Dynamic Security与 C/C 客户端库解决了多处可能引起崩溃、误断连或行为不符合 MQTT 规范的问题。读完本文你将逐一理解这 17 项修复的来龙去脉并掌握对应配置项如max_queued_messages、idle_timeout、max_keepalive、per_listener_settings在源码中的实现原理与正确用法。版本概览一次覆盖四大模块的稳定性修复2.0.22 的修复清单按模块可以划分为四个部分Broker共 13 项涵盖 Windows 平台崩溃、lazy 桥接idle_timeout失效、max_queued_messages 0语义错误、--version退出码、$CONTROL消息处理崩溃、Linux 启动参考时钟选择、断连原因误报、WITH_OLD_KEEPALIVE编译、WebSocket PING、安全 WebSocket、WITH_EPOLLno退出崩溃以及 keepalive 边界过期问题Dynamic security plugin1 项修复保存配置时内存释放不匹配导致的内存跟踪错误Client librarylibmosquitto3 项涉及 C 符号被链接期优化LTO移除、TLS 错误被误判为协议错误、部分架构下 CMake 链接错误测试1 项修复单 CPU 系统上 SSL 证书测试的不稳定性。下文按模块逐一展开并在每个修复点结合本仓库源码给出实现层面的佐证。Broker 侧修复深度解析Windows 平台使用log_dest stdout启动即崩溃2.0.22 修复了 Windows 上若配置log_dest stdoutBroker 在启动阶段直接崩溃的问题。Windows 下的标准输出处理与 Unix 存在差异该修复让日志目标解析在 Windows 上按正确路径初始化。涉及日志输出与配置解析的相关代码位于 src/logging.c 与 src/conf.c跨平台行为差异则集中在服务层 src/service.c。如果你的部署环境是 Windows 且启用了 stdout 日志升级到 2.0.22 即可规避该崩溃。桥接Bridgelazy 桥的idle_timeout不再失效idle_timeout是 lazy 类型桥接的核心参数。根据 mosquitto.conf 的说明Set the amount of time a bridge using the lazy start type must be idle before it will be stopped. Defaults to 60 seconds.即lazy 桥在空闲多少秒后自动断开。该值默认 60 秒解析逻辑位于 src/conf.c且强制最小值为 1 秒低于 1 会被钳制并打印 NOTICE 日志}else if(!strcmp(token, idle_timeout)){ ... if(conf__parse_int(token, idle_timeout, cur_bridge-idle_timeout, saveptr)){ ... } if(cur_bridge-idle_timeout 1){ log__printf(NULL, MOSQ_LOG_NOTICE, idle_timeout interval too low, using 1 second.); cur_bridge-idle_timeout 1; }2.0.22 修复的问题在于此前 lazy 桥连接建立后空闲计时器从未被正确触发导致桥接永远不按idle_timeout断开。lazy 桥的完整工作链路是当排队消息数超过threshold默认 10见 mosquitto.conf时src/database.c 会把lazy_reconnect置为 true随后 src/bridge.c 据此触发重连连接空闲后则应依据idle_timeout停止。本次修复确保 lazy 桥在达到空闲时间后能够按预期断开避免闲置连接长期占用资源。配置示例connection lazy-edge address edge.example.com:1883 start_type lazy threshold 10 idle_timeout 60 topic # bothmax_queued_messages 0现在真正表示无限制#3244这是本次发布中影响面最广的语义修复之一。max_queued_messages用于限制为离线或慢速客户端排队的消息条数默认值为 1000src/conf.c 中config-max_queued_messages 1000;解析入口在 src/conf.c。在 2.0.22 之前将max_queued_messages设为 0 并没有被正确视为不限制条数导致某些场景下消息被意外丢弃。修复后的判断逻辑在 src/database.c 的db__ready_for_flight()与 src/database.c 的db__ready_for_queue()中均有体现当max_queued_messages 0时仅依据字节限制max_queued_bytes判断当两者都为 0 时直接返回 true即完全不受限if(db.config-max_queued_messages 0 db.config-max_queued_bytes 0){ return true; } ... if(db.config-max_queued_messages 0){ return valid_bytes; /* 仅按字节数判断 */ } if(db.config-max_queued_bytes 0){ return valid_count; /* 仅按条数判断 */ }同时src/handle_publish.c 中的丢包判定也改为仅在max_queued_messages 0时才按条数丢弃。仓库中的测试配置 test/broker/03-publish-qos1-queued-bytes.conf 正是用max_queued_messages 0配合max_queued_bytes 400来验证条数不受限、仅按字节限流的行为。参考配置写法# 只限制排队字节数不限制消息条数 max_queued_messages 0 max_queued_bytes 1000000 # 或者两者都设 0完全不做排队限制谨慎使用 # max_queued_messages 0 # max_queued_bytes 0--version退出码与输出修复#3267此前mosquitto --version在打印版本信息后可能返回非零退出码导致脚本化部署中基于退出码做判断的逻辑失真。Broker 启动、运行、退出时都会记录版本字符串见 src/mosquitto.c、src/mosquitto.c 与 src/mosquitto.c 中的mosquitto version %s ...日志。本次修复统一了版本输出行为使mosquitto --version能像标准 CLI 工具一样正常返回成功状态便于在安装脚本、CI 流水线中校验 Broker 版本。桥接上的$CONTROL消息崩溃修复#3261该修复针对一个组合场景当per_listener_settings设为 true、桥接正在做主题重映射topic remapping、且通过桥接收到$CONTROL消息时Broker 可能崩溃。$CONTROL是 Mosquitto 的控制面主题$CONTROL/feature其处理流程在 src/control.c先查全局插件的 control 回调若未命中且per_listener_settings为 true则回退到该客户端所属 listener 的安全选项中去查找——而桥接连接可能没有与之关联的 listener 上下文context-listener为空此前代码路径会对空指针解引用。相关源码甚至保留了一段专门的警告if(cb_found NULL db.config-per_listener_settings){ if(!context-listener){ log__printf(NULL, MOSQ_LOG_WARNING, Warning: $CONTROL command received from client with no listener, when per_listener_settings is true.); log__printf(NULL, MOSQ_LOG_WARNING, If this is a bridge, please be aware this does not work.); return MOSQ_ERR_SUCCESS; } ... }Broker 内置的 control API$CONTROL/broker/v1注册逻辑见 src/broker_control.c。修复后在per_listener_settings true环境下通过桥接接收$CONTROL消息不再触发崩溃。per_listener_settings的默认值为 false启用方式为在配置顶部任何安全设置之前声明per_listener_settings true注意 src/conf.c 会强制该选项必须先于其他安全设置出现否则报错。Linux 启动时参考时钟选择修复#3238Broker 内部大量使用当前时间驱动会话过期、消息过期、桥接重连等逻辑。时间源取自mosquitto_time()在各事件循环入口刷新db.now_s见 src/loop.c、src/mosquitto.c、src/mux_epoll.c 等底层基于clock_gettime(CLOCK_REALTIME, ...)见 src/database.c。本次修复纠正了 Linux 启动阶段对参考时钟reference clock的选择错误避免在某些系统时钟配置下出现时间基准错乱从而影响依赖时间计算的特性如会话过期、消息过期。该修复对长时间运行、依赖$SYS与持久化时间戳的生产部署尤为重要。客户端断连原因误报内存不足的修复#3253此前部分客户端断连会被错误地记录为 out of memory给排障带来误导。修复后断连原因按真实错误码归因日志与DISCONNECT原因码都能反映实际情况。从 src/handle_disconnect.c 与 src/context.c 的断连处理路径看Broker 会依据错误码选择日志级别与原因码本次修复保证了错误分类的准确性。升级后排查断连问题时应优先查看 broker 日志中实际的 reason 信息而非依赖内存不足这类笼统提示。WITH_OLD_KEEPALIVE编译修复#3250Mosquitto 维护着两套 keepalive 检查机制默认的新版 O(1) 环形缓冲区实现以及旧的每 5 秒全量扫描实现。旧版可通过make WITH_OLD_KEEPALIVEyes启用CMake 对应选项见 src/CMakeLists.txt 与 src/CMakeLists.txt。2.0.22 修复了该编译选项下出现的构建错误使依赖旧机制的存量部署可以继续编译升级。两套机制的差异在 src/keepalive.c 的注释中有详细说明旧版扫描全部在线客户端、复杂度 O(n)在 6 万客户端规模下会带来低个位数百分比的 CPU 开销新版使用包含max_keepalive*1.51个槽位的环形缓冲区复杂度 O(1)。Windows 安装器补充 Broker 链接文件#3269本次发布为 Windows 安装器补充了 Broker 的链接器导出文件解决 Windows 平台下符号导出缺失导致的构建或运行问题相关导出定义可参考 src/linker.syms 以及 installer/mosquitto.nsi、installer/mosquitto64.nsi 中打包的文件清单。WebSocketWindows PING 发送修复#3272与安全 WebSocket 修复#1211#3272Windows 平台上 WebSocket 连接的 PING 帧此前不会按预期发送影响 WebSocket 客户端的长连接保活。修复位于 WebSocket 相关实现src/websockets.c 与 lib/net_ws.c。#1211secure WebSocketwss在特定条件下存在连接问题本次一并修复涉及 TLS 与 WebSocket 握手叠加路径的处理。使用 WebSocket 监听器的典型配置如下listener 8083 protocol websockets listener 8084 protocol websockets cafile /path/to/ca.crt certfile /path/to/server.crt keyfile /path/to/server.keyWITH_EPOLLno时退出崩溃修复#3302Mosquitto 在 Linux 上默认使用 epoll 多路复用src/mux_epoll.c关闭后回退到 poll 实现src/mux_poll.c。2.0.22 修复了WITH_EPOLLno构建下 Broker 退出阶段的崩溃保证使用 poll 后端的部署可以干净地关闭。keepalive 等于max_keepalive的客户端被错误过期#3226/#3286这是本次发布中与 MQTT v5 保活语义最相关的修复。max_keepalive用于限制客户端可用的最大 keepalive 值默认 0 表示不限制最大值 65535详见 mosquitto.conf。默认的新版 keepalive 检查使用环形缓冲区客户端按预期过期时刻now keepalive*1.5放入槽位当时间推进到该槽位且链表非空时其中的客户端被判为过期。问题在于当客户端 keepalive 恰好等于max_keepalive时其过期时刻刚好落在检查窗口边界上会被错误地立即判为过期断开。修复引入了keepalive_add_time记录客户端入队时间见 src/keepalive.cint keepalive__add(struct mosquitto *context) { ... DL_APPEND2(keepalive_list[calc_index(context)], context, keepalive_prev, keepalive_next); context-keepalive_add_time db.now_s; ... }并在检查时加以区分src/keepalive.c 中的注释直接说明了该修复的动机/* keepalive_add_time lets us account for the client adding itself to the keepalive * list when its last_msg_in value is greater than the last_keepalive_check. * Without this, the client would be expired if it has keepalive max_keepalive. */ if(context-keepalive_add_time last_keepalive_check net__is_connected(context)){ /* Client has exceeded keepalive*1.5 */ do_disconnect(context, MOSQ_ERR_KEEPALIVE); }仓库测试 test/broker/01-connect-max-keepalive.py 与 test/broker/12-prop-server-keepalive.py 覆盖了max_keepalive的拒绝与 MQTT v5 server keepalive 行为test/broker/16-config-parse-errors-without-tls.py 则验证了越界值如 65536、-1会被配置解析器拒绝。Dynamic security plugin配置保存的内存释放修复动态安全插件插件源码位于 plugins/dynamic-security包括 config.c、config_init.c 等在保存配置时存在内存释放不匹配mismatch memory free导致内存跟踪memory tracking计数不正确。该问题虽不直接表现为崩溃但会污染 Broker 的内存统计与调试信息。2.0.22 统一了配置保存路径中的分配/释放配对使内存跟踪恢复准确。客户端库libmosquitto修复C 符号在链接期优化LTO下被移除#3259使用链接期优化编译时libmosquittoppC 封装见 lib/cpp/mosquittopp.cpp的 C 符号可能被优化器判定为未使用而从导出表中移除导致链接失败。本次修复保证了 LTO 构建下 C 接口符号依然可见对启用 LTO 的发行版打包尤为重要。符号导出列表可参考 lib/linker.version。TLS 错误被误设为协议错误导致mosquitto_loop_start()线程退出#3258这是一个非常隐蔽的客户端问题非 TLS 错误例如首次连接时没有可用的 broker被错误地归类为协议错误protocol error进而导致mosquitto_loop_start()启动的线程在首次连接失败后直接退出而正确行为应是在后台持续重试。客户端事件循环的错误收尾逻辑在 lib/loop.c 的mosquitto__loop_rc_handle()中出错时关闭 socket并依据客户端状态决定是否调用 disconnect 回调读取路径见 lib/loop.c 的mosquitto_loop_read()。修复后非 TLS 错误不再污染错误码mosquitto_loop_start()线程在 broker 暂时不可用时能保持存活并按预期重连。如果你的客户端程序依赖首连失败后由 loop 线程自动重试的行为2.0.22 是必须升级的版本。CMake 下部分架构链接错误#3167修复了部分架构architecture在使用 CMake 构建 libmosquitto 时出现的链接器错误完善了跨架构的构建兼容性。测试修复单 CPU 系统上的 SSL 证书测试测试套件中的08-ssl-connect-cert-auth-expired与08-ssl-connect-cert-auth-revoked两个用例在单 CPU 系统上运行时不稳定本次通过调整时序/并发处理使其在单核环境下也能稳定通过相关测试位于 test/ssl 目录。这也从侧面说明 2.0.22 对资源受限环境的关注不止于运行时行为还延伸到测试可靠性。升级与验证建议升级前确认你的配置中是否使用了max_queued_messages 0、max_keepalive尤其等于客户端 keepalive 值、lazy 桥idle_timeout、per_listener_settings true等本次修复涉及的选项这些是升级收益最直接的场景。升级后验证运行mosquitto --version确认退出码为 0观察 Broker 日志确认不再出现误报的 out of memory 断连记录检查 WebSocket / wss 客户端的 PING 保活与长连接稳定性若使用 MQTT v5 客户端重点验证 keepalive 等于max_keepalive时连接不被误断。客户端侧使用mosquitto_loop_start()且依赖自动重连的程序务必升级到 2.0.22 以修复首次连接失败时 loop 线程退出的问题。总而言之2.0.22 没有引入新功能但它修正了多条直接影响生产稳定性的缺陷——从 Windows 启动崩溃、lazy 桥空闲不断开、max_queued_messages 0语义错误到 keepalive 边界误判与客户端 TLS 错误分类。对于运行 Mosquitto 2.0.x 系列的生产环境这是一个低风险、高收益的必升版本。赞分享后端消息队列消息路由【免费下载链接】mosquittoEclipse Mosquitto - An open source MQTT broker项目地址https://gitcode.com/gh_mirrors/mos/mosquitto点击查看免费下载相关推荐SafeLine 忘记或泄露数据库密码时如何用管理脚本重置 POSTGRES_PASSWORD 并重启容器SafeLine 忘记或泄露数据库密码时如何用管理脚本重置 POSTGRES_PASSWORD 并重启容器 SafeLine雷池的控制台配置存放在 Pos后端消息队列消息路由Tolaria ADR-0100用前端合成的 Vault 根行统一文件夹导航模型Tolaria ADR 0100用前端合成的 Vault 根行统一文件夹导航模型 Tolaria 的侧边栏文件夹树需要让用户能一键回到 Vault 根目录、浏后端消息队列消息路由Eclipse Mosquitto 1.6.3 发布详解Broker、客户端库与命令行工具的关键缺陷修复Eclipse Mosquitto 1.6.3 发布详解Broker、客户端库与命令行工具的关键缺陷修复 导读 Mosquitto 1.6.3 是 Eclip后端消息队列消息路由上一篇Theano大规模数据集处理高效数据加载与预处理下一篇neural-doodle多分辨率支持从图标到壁画的全尺寸创作创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考