- 物联网
- 消息队列
- 后端
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
本文基于 Eclipse Mosquitto 项目官方博客 Two!(2011-10-25 发布)整理而成。该文发布于项目两周岁之际,记录了 2010 年 10 月至 2011 年 10 月间 Mosquitto 从 0.8.3 迈向 0.13 的关键技术演进:移除 SQLite 依赖、完成 Windows 原生移植、支持 MQTT 3.1、持续向 IBM RSMB 特性对齐,以及对 1.0 版本的规划。本文将以这篇里程碑文章为主线,结合当前仓库中的源码与文档,逐条还原每一项技术决策背后的实现细节,帮助读者理解 Mosquitto 的架构设计初衷与后续演进脉络。
一、两周年里程碑:0.8.3 → 0.13 的年度成绩单
2011 年 10 月 25 日,Mosquitto 项目迎来两周岁生日。彼时项目版本已从 0.8.3 推进到 0.13,官方博客在 Two! 中总结了这一年的核心成果:
- 彻底移除 SQLite 依赖:内存与磁盘上的数据存储全部改由自定义例程实现,broker 变得更加紧凑(compact)、性能更好(better performing)且实现更为优雅(more elegant);
- Windows 原生移植:为后续摆脱 Cygwin 依赖、提供安装程序与 Windows 服务支持埋下伏笔;
- MQTT 3.1 支持:紧跟 2010 年更新的 MQTT v3.1 规范;
- Python 模块大幅改进:为后来的异常式 API 演进做准备;
- 向 RSMB(IBM Really Small Message Broker)特性对齐:以"drop-in replacement"为目标;
- 进入 Debian 与 Ubuntu 官方软件包仓库;
- 客户端代码被 Facebook 的 iPhone 应用采用——这是社区影响力的有力佐证。
需要说明的是,这些是 2011 年时间点上的历史事实;当前仓库中的 Mosquitto 已经演进为同时支持 MQTT v3.1、v3.1.1 与 v5.0 的成熟 broker,本文后续章节将结合仓库现状逐项展开。
二、移除 SQLite:从数据库依赖到自定义内存存储
2.1 历史背景:为什么要离开 SQLite
在 0.9 之前的版本中,Mosquitto 使用 SQLite 存储客户端与消息数据,并连带依赖 pcre 与 sqlite3-pcre 两个附加库。2010 年 11 月发布的 Version 0.9 released 明确记录了这一重大变更:
"Client and message data is now stored in memory with custom routines rather than a sqlite database. This removes the dependencies on sqlite, pcre and sqlite3-pcre."
移除 SQLite 后,broker 在每秒处理消息数与内存占用两方面都获得了明显改善——这正是博客文中"more compact, better performing and more elegant"三组形容词的出处。
2.2 仓库中的实现证据
当前仓库中,这一架构决策的痕迹依然清晰可辨:
- 持久化格式:
src/persist.h定义了自有的磁盘数据库格式,MOSQ_DB_VERSION 6为当前数据库版本,DB_CHUNK_CFG、DB_CHUNK_BASE_MSG、DB_CHUNK_CLIENT_MSG、DB_CHUNK_RETAIN、DB_CHUNK_SUB、DB_CHUNK_CLIENT六种 chunk 类型分别承载配置、基础消息、客户端消息、保留消息、订阅与客户端数据,读写实现分布在 persist_read.c、persist_write.c 及对应 v5 变体中; - SQLite 的残余角色:仓库中仍保留
plugins/persist-sqlite/目录,但它已不再是 broker 的内置依赖,而是作为一个可选的持久化插件存在。其 test.conf 展示了插件的加载方式:
persistence_location . plugin ./mosquitto_persist_sqlite.so plugin_opt_page_size 4096 plugin_opt_flush_period 5这一设计印证了博客中"broker 更优雅"的说法:核心 broker 不再背负数据库依赖,需要 SQLite 持久化的用户通过插件机制按需启用即可。
2.3 遗留兼容代码的清理时间线
从 Version 0.11 released 的变更日志可以看到,旧 SQLite 代码的清理是一个渐进过程:
- 0.9:提供可选的旧 SQLite 数据库导入支持(默认编译开启);
- 0.10:导入支持默认关闭;
- 0.11:彻底移除全部旧 SQLite 代码。
这条时间线展示了 Mosquitto 团队在破坏性变更上的稳健策略——先保留导入能力过渡,再逐步移除,最终完全切换。
三、MQTT 3.1 支持:用户名/密码认证的引入
3.1 版本能力在源码中的落点
MQTT 3.1 的核心在于 CONNECT 报文携带用户名/密码标志位。当前仓库在 include/mosquitto/mqtt_protocol.h 中完整保留了各协议版本的常量定义:
#define PROTOCOL_NAME_v31 "MQIsdp" #define PROTOCOL_VERSION_v31 3 #define PROTOCOL_NAME "MQTT" #define PROTOCOL_VERSION_v311 4 #define PROTOCOL_VERSION_v5 5注意 MQTT 3.1 的协议名是MQIsdp(而非 v3.1.1/v5.0 的MQTT),这是 3.1 规范的重要识别特征。同一头文件还定义了完整的报文类型(CMD_CONNECT、CMD_PUBLISH、CMD_SUBSCRIBE等)与 CONNACK 返回码枚举(CONNACK_REFUSED_BAD_USERNAME_PASSWORD = 4等),可直接作为协议级事实依据。
3.2 0.9 时期的实现局限
博客文中提到的"MQTT 3.1 support"在 0.9 时代是分层的:
- 客户端与客户端库:完整支持 v3.1,
mosquitto_pub/mosquitto_sub与 libmosquitto 均可携带用户名密码; - broker:兼容 v3.1 连接,但当时不提供任何用户名/密码校验机制——Version 0.9 released 原文为 "The broker supports the username and password connection flags, but will not do anything with the username and password",并计划在 0.10 补齐。
这一能力缺口随后由 password file 与 ACL 机制填补,如今可通过mosquitto_passwd(源码见 apps/mosquitto_passwd/mosquitto_passwd.c)与 aclfile.example 配置实现完整的认证授权。
3.3 如今的三协议共存
从 include/mosquitto/mqtt_protocol.h 可以看出,当前 broker 同时支持 v3.1、v3.1.1(协议版本 4)与 v5.0(协议版本 5)三种协议版本,这正是从 0.9 时代单一 v3.1 支持不断演进的结果。
四、对标 RSMB:功能完备性与差异化超越
4.1 "drop-in replacement" 目标
博客文与 Version 0.9 released 都明确提到:Mosquitto 的一个核心目标是成为 IBM RSMB 的**可直接替换(drop-in replacement)**方案,另一目标则是"做得比 RSMB 更多"。
0.9 时期两者均有进展:
- 对齐 RSMB:
port配置变量的行为改为与 RSMB 一致(仅作用于默认 listener,只能出现一次); - 超越 RSMB:新增IPv6 支持——RSMB 当时并不支持 IPv6。
4.2 桥接(Bridge)特性是最后一块拼图
两周年博文直言 1.0 的验收标准是"完整的 RSMB 特性(除少数冷门功能外)",而当时尚未完成的主要是:
- 部分桥接(bridge)特性;
- 完整的配置热加载(configuration reloading)。
桥接功能在今天的仓库中已经非常成熟:核心实现位于 src/bridge.c(约 290 处桥接相关代码),配置说明见 man/mosquitto.conf.5.xml 中 "Configuring Bridges" 章节;桥接还可以与本地保留消息、topic 重映射等特性组合使用(参考 06-bridge-b2br-remapping.py 等测试)。
4.3 配置热加载的最终落地
配置热加载在两周年时仍属规划项,如今已通过SIGHUP 信号实现。src/signals.c 中可以看到完整的处理链路:
if(signal == SIGHUP){ flag_reload = true; }主循环检测到flag_reload后依次执行listeners__reload_all_certificates()、broker_control__reload()与bridge__reload()(src/signals.c 第 104-119 行区域),实现不重启即重载配置。这一行为也在 man/mosquitto.8.xml 的 SIGHUP 条目中正式文档化。
五、Windows 原生移植:从 Cygwin 依赖到原生服务
5.1 年度进展与后续规划
两周年博文确认,Windows 原生移植已在 0.9 期间部分完成(Version 0.9 released 称当时会暂时丢失部分功能,如配置修改与持久化)。博文同时预告了 0.14 的目标:改进 Windows 移植、取消单独的 Cygwin 版本、提供 Windows 安装程序、让 Mosquitto 以正规 Windows 服务方式运行。
5.2 仓库中的实现
这些规划最终全部落地,仓库中的证据包括:
- NSIS 安装脚本:installer/mosquitto.nsi 与 installer/mosquitto64.nsi,分别面向 32/64 位构建;
- Windows 服务支持:broker 的 Windows 服务逻辑位于 src/service.c,其中包含
mosq%d_reload事件(src/signals.c 第 154 行附近)等平台适配代码; - 线程抽象层:common/winthread_mosq.c 与 common/winthread_mosq.h 提供了跨平台线程封装,使 libmosquitto 在 Windows 与 POSIX 平台上保持一致的行为。
六、Python 模块:从回调式到异常式 API 的演进方向
两周年博文指出,Python 模块虽已大幅改进,但"还可以更 Pythonic"——当时的规划是让 API 抛出异常(throw exceptions)而非返回整数错误码,作者甚至在文中坦言"需要一位 Python 专家的帮助"。
这一演进方向的早期铺垫在 Version 0.9 released 中可以看到:Python 回调函数开始可选地接收额外参数,用于返回构造Mosquitto()时传入的 user 对象。而从 0.9 起,Debian/Ubuntu 上的 Python 绑定包也按 Debian 命名规范由libmosquitto0-python更名为python-mosquitto。
需要说明:当前仓库中的 libmosquitto 底层 API 仍以返回整数错误码(如MOSQ_ERR_INVAL)为约定,C 语言接口的对应约束在 lib/libmosquitto.h 等头文件中定义,Python 绑定的具体形态请以对应发行版的打包为准。
七、进入 Linux 发行版:Debian 与 Ubuntu 打包
7.1 年度成就
两周年博文将"被 Debian 打包……以及 Ubuntu 打包"列为年度亮点。仓库中的相关佐证散见于:
- 早期打包记录:www/posts/2010/09/debian-packages.md、www/posts/2010/05/fedora-packages-available.md 等博客文章记录了各发行版打包的推进过程;
- 包配置文件:libmosquitto.pc.in 与 libmosquittopp.pc.in 提供了 pkg-config 元数据,是发行版打包的基础设施。
7.2 安装方式现状
如今,用户可以通过发行版包管理器直接安装 Mosquitto,也可参考 README-compiling.md 从源码编译。仓库根目录的 Makefile 与 CMakeLists.txt 同时提供两套构建体系,前者对应config.mk配置,后者面向 CMake 用户。
八、社区力量:Bug 反馈与生态应用
博文最后特别致谢了社区贡献:"无数被报告的 bug、修复、建议与兴趣"。仓库中的证据包括:
- 详尽的历史变更日志:ChangeLog.txt 记录了从早期版本到当前的完整演进;
- 贡献指南:CONTRIBUTING.md 规范了社区协作流程;
- 致谢名单:THANKS.txt 列出了历届贡献者;
- 生态应用:博客提及 Mosquitto 客户端代码被 Facebook iPhone 应用采用——这是 2011 年的历史事实,说明其轻量客户端库在移动场景的价值。
九、展望:1.0 的验收标准与后续演进
9.1 2011 年时的 1.0 规划
博文为 1.0 设定了明确验收标准:完整实现 RSMB 特性(排除少数冷门项),具体待办包括补齐桥接特性与完整配置热加载;同时推进 Windows 移植、安装程序与 Windows 服务支持(计划落在 0.14);Python 模块则追求更 Pythonic 的异常式 API。
9.2 从今天的仓库看规划兑现
对照当前仓库,上述规划均已成真:
- 桥接:src/bridge.c 提供完整实现,man/mosquitto.conf.5.xml 的 "Configuring Bridges" 章节给出详细配置项(
address、bridge_attempt_unsubscribe等); - 配置热加载:通过 SIGHUP 实现(src/signals.c);
- Windows 支持:installer/mosquitto.nsi、src/service.c;
- 持久化体系:persist.h 与 persist_read.c、persist_write.c 构成自研格式的完整读写实现,man/mosquitto.conf.5.xml 中的
persistence、persistence_file、persistence_location、autosave_interval(默认 1800 秒)、autosave_on_changes、persistent_client_expiration(支持2m、14d、1y等时长语法)等配置项共同支撑运维; - 协议能力:include/mosquitto/mqtt_protocol.h 显示已扩展至 MQTT v5.0 的完整属性系统(
MQTT_PROP_*枚举)与 v5 返回码(MQTT_RC_*)。
9.3 一路走来的版本脉络
从两周年时的 0.13,到如今仓库中的成熟版本,Mosquitto 走过的路径可以在以下文件中完整追溯:
- 各版本发布博客:www/posts/2010/、www/posts/2011/ 等目录下的发布公告;
- 官方变更日志:ChangeLog.txt;
- 协议级演进证据:include/mosquitto/mqtt_protocol.h。
结语
两周年博文以一句轻描淡写的 "All in all I think it should be a good year" 收尾,而其背后是 SQLite 依赖的彻底剥离、Windows 原生移植的推进、MQTT 3.1 的支持、向 RSMB 特性对齐的执着,以及一个活跃社区的持续反馈。透过当前仓库的源码回看,这些当年的"年度计划"无一例外地沉淀成了今天的架构基石:自研的紧凑持久化格式、完整的桥接与热加载能力、跨平台的服务化部署,以及从 v3.1 到 v5.0 的协议全支持。对于想要理解 Mosquitto 设计哲学的读者而言,这篇两周年总结连同仓库中的实现,共同构成了一份完整的演进档案。
- 物联网
- 消息队列
- 后端
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
相关推荐
Eclipse Mosquitto 项目两周年回顾:从 0.8.3 到 0.13 的架构演进与 1.0 路线图
Eclipse Mosquitto 项目两周年回顾:从 0.8.3 到 0.13 的架构演进与 1.0 路线图 Mosquitto 作为一款开源 MQTT Br
后端消息队列消息路由Eclipse Mosquitto终极指南:轻量级MQTT broker核心功能解析
Eclipse Mosquitto终极指南:轻量级MQTT broker核心功能解析 Eclipse Mosquitto是一款开源的 轻量级MQTT broke
物联网消息队列后端从依赖臃肿到轻量演进:Flying Saucer移除JSR305的技术之路
从依赖臃肿到轻量演进:Flying Saucer移除JSR305的技术之路 一、痛点直击:JSR305依赖的"甜蜜负担" 你是否也曾遭遇过这些困境:项目构建时频
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考