MQTT Broker国产替代:许可证合规、选型对比与迁移实操
2026/9/14 7:09:08 网站建设 项目流程

上个月一个朋友找我救火,他们做智慧园区项目,设备端通过 4G 模块用 MQTT 上报数据,服务端原本打算直接用 Mosquitto 顶上,结果交付前法务审核流程一看 LICENSE 文件,立刻卡住:项目里混着 EPL、Apache 2.0、还有某个依赖带了 AGPL,团队被要求"把整个平台开源"或者"替换掉所有有传染风险的组件"。我陪他把几个国产 MQTT 协议栈和 broker 从头到尾对比了一圈,最后选了替代方案,项目才顺利过审。这件事让我意识到,在 MQTT 生态里聊"替代 Mosquitto / EMQX",真正难点从来不是性能,而是开源版权边界和商用风险怎么算清楚。

这篇文章就围绕这个主题展开,适合正在做物联网平台选型、被甲方要求国产化适配、或者对开源许可证一脸迷茫的架构师和后端工程师。我会把许可证分清楚,盘点目前值得关注的国产候选方案,给出一份从 Mosquitto 迁到 NanoMQ 的实操记录,最后聊聊许可证之外那些更容易被忽略的商用风险。整篇不是我抄文档,是我这几年实际踩坑后的总结。

1. 为什么一个看似好用的 MQTT 方案,会卡在法务审批上

1.1 一个差点让项目翻车的小故事

先说朋友那个项目。设备端用的是 EC20 之类的 4G 模块,AT 指令里配好 MQTT 参数,数据上行到 broker,平台侧通过 Node-RED 做 OPC UA 转 MQTT,前端用 Vue3 加 mqtt.js 订阅实时状态。这套链路跑得很顺,Mosquitto 虽然是国外基金会项目,但部署简单、资料多,团队一天就搭起来了。

问题出在交付材料。政企类项目验收时要提交第三方组件清单和 license 声明,法务把 broker 相关的 LICENSE 文件拉出来一看,里面既有 EPL 又有 AGPL 的依赖项,当场要求要么全量替换,要么把整个平台源码开放。朋友一开始还不信,说 Mosquitto 不是 BSD 吗?其实不是。这个误解如果带到合同执行阶段,代价会非常大。

1.2 替换需求通常来自三类场景

我在不同项目里见到的"替换需求"基本可以归成三类。

第一类是 license 合规评估不通过。银行、政务、医疗这类客户对开源许可证极其敏感,他们内部有 license 扫描工具,凡是出现 GPL/AGPL 字样的组件直接拉黑。即使实际风险没那么高,法务也不会去细抠边界,最省事的办法就是让供应商换掉。第二类是信创和国产化要求。很多招标文件直接写"核心组件需国产化、需提供软著证书、需适配国产操作系统和芯片",Mosquitto 是 Eclipse 基金会项目,虽然开源,但很难拿出让甲方满意的国产化证明材料。第三类是商业路线顾虑。团队担心 EMQX 企业版和开源版的功能边界后续会收窄,或者不希望把核心消息链路押在一个由商业公司主导 roadmap 的开源项目上,想找更能"拿捏"的替代品。

无论哪一类,本质上都在问同一个问题:我手上这个开源项目,到底什么能商用、什么不能商用、边界在哪里。搞不清楚这个问题,换谁心里都没底。

2. 许可证对比:EPL 2.0、Apache 2.0、AGPL/SSPL 的传染边界在哪里

2.1 经常被误读的 Mosquitto 许可证

先纠正一个高频误区:Mosquitto 不是 GPL,也不是 BSD。目前主流的 Mosquitto 2.x 版本采用 Eclipse Public License 2.0(EPL 2.0)和 Eclipse Distribution License 1.0(EDL 1.0)双重许可,使用方可以在两者中选一个来遵守。

EPL 2.0 要理解成"文件级 copyleft"。它要求的是:如果你修改了 Mosquitto 源码中某个 EPL 文件,那么那个文件及其衍生部分需要继续以 EPL 开放;但你把 Mosquitto 作为一个独立的 broker 进程跑起来,没有改它的代码,你的业务系统不需要开源。这比 GPL 温和很多。EDL 1.0 则基本等价于 BSD-3-Clause,几乎没有附加义务。

真正会踩雷的场景是什么?是有人把 Mosquitto 静态编译进自己出售的硬件固件里,还改了源码,然后闭源分发。这种情况下,EPL 的触发条件就比较麻烦,必须把修改部分的开源代码提供给客户。所以不是说 Mosquitto 不能商用,而是使用方式决定义务边界。

2.2 EMQX 和国产替代方案的实际许可情况

EMQX 开源版的核心代码是 Apache License 2.0,这是几乎所有宽松许可证里最友好的一种:允许自由使用、修改、分发、商用,不需要开源你的衍生作品,只要保留原始版权声明即可。换句话说,如果团队只是把 EMQX 部署起来做接入层,闭源自己的业务平台,这是完全合规的。

但要注意两点。第一,EMQX 企业版是闭源的,像部分数据集成、集群管理增强、多租户这类高级功能不会进开源版。第二,EMQX 虽然是国内公司主导,但它的开源路线图由公司决策,存在未来把更多能力移到商业版的可能。正因为如此,很多做国产化替代的团队会顺势看一眼 NanoMQ、gmqtt 这些同样出自国内团队的项目,提前做备选评估。

NanoMQ 由 EMQ 公司开源,许可证是 Apache 2.0;gmqtt 是个人主导的 Go 语言实现,也是 Apache 2.0。从许可证角度,这几个都比 Mosquitto 的 EPL 更容易向法务解释。

2.3 AGPL/SSPL 才是真正要躲的坑

在 MQTT 生态里直接出现 AGPL/SSPL 的 broker 不算多,但依赖树里混进 AGPL 包的情况我见过。AGPL 和 GPL 最大的区别,是它把"分发"这个触发条件扩展到了"通过网络提供服务"。也就是说,你就算不卖软件,只是把服务部署到公网上让用户访问,也必须把对应衍生部分的源码开放出来。对做 SaaS 的团队来说,这是最伤的一种许可。

SSPL 是 MongoDB 搞出来的,比 AGPL 更激进,除了服务本身,连"提供该服务所必需的管理层软件"都要开源。所以一看到 SSPL,基本可以直接换方案。

我用这样一张表给团队说明风险等级:

许可证分发时是否要开源SaaS/网络服务是否受限主要风险风险等级
Apache 2.0不需要,保留声明即可不限很低
EPL 2.0修改过的文件需开源不限修改边界需要说明中低
AGPL 3.0需要需要开源衍生部分
SSPL 1.0需要扩展到管理代码很高很高

2.4 别只看主 LICENSE,依赖扫描必须做

有一次我们评估某个 broker 时,主许可证明明是 Apache 2.0,但依赖列表里躺着一个 GPL 的压缩库,如果按 GPL 传染性来理解,整个 broker 的分发都要受影响。后来把那个库换掉才放心。

建议选型阶段就引入 license 扫描工具,不要等到法务介入。Go 项目可以用 go-licenses,Node 项目用 license-checker,Java 项目用 License Maven Plugin,C++ 项目可以用 FOSSA 之类商业工具。扫描完之后生成一份依赖清单,连同主 LICENSE 文件一起存档,后面交付的时候直接给甲方,能省很多扯皮时间。

3. 国产候选盘点:NanoMQ、gmqtt 与自研接入层的真实差异

3.1 先分清"协议栈"和"broker"这两个词

聊国产替代之前,必须先把词说清楚,否则很容易鸡同鸭讲。MQTT 协议栈指的是实现 MQTT 协议编解码、会话管理、QoS 状态机、遗嘱保留逻辑的那层代码库;broker 是指真正跑起来对外提供接入服务的进程,Mosquitto、EMQX、NanoMQ 都是 broker。gmqtt 更准确地说是一个协议栈加可嵌入的 broker 库,适合嵌到自己的程序里,而不是开箱即用的独立服务。

按标题里的说法"国产 MQTT 协议栈",实际替换目标要非常明确。如果只是想换一个服务端 broker,优先看 NanoMQ;如果是要把 MQTT 接入融合进自己的微服务,看 gmqtt;如果打算从设备端 SDK 到服务端全部自己实现,那就是另一个量级的工作了。

3.2 NanoMQ:最像 Mosquitto 的轻量级替代

NanoMQ 是 EMQ 公司开源的一个轻量级 MQTT broker,Apache 2.0 许可,用 C++ 实现,底层基于 NNG 的异步 I/O 模型。它支持 MQTT 3.1.1 和 5.0,保留消息、遗嘱消息、共享订阅这些都有,还内置了 WebSocket 监听器,可以做桥接,像是把一堆常见边缘网关需要的集成能力揉进去了。

为什么说它最像 Mosquitto 的替代?因为两者定位都偏轻量、单机部署友好。Mosquitto 胜在历史久、资料多、极端稳定,但它的功能演进非常慢,集群、规则引擎这些基本不指望。NanoMQ 性能更强,尤其是在高并发小报文场景下表现出色,而且团队有商业公司支撑,文档更新和 issue 响应都比纯社区项目快。

部署非常简单。用 Docker 的话一条命令就起来: bash docker run -d --name nanomq -p 1883:1883 emqx/nanomq:latest

配置文件默认在 /etc/nanomq.conf 或 /nanomq.conf,具体路径看镜像版本。它使用 HOCON 风格的配置格式,和 Mosquitto 的扁平键值风格完全不同,初看有点不适应,但结构更清晰。我的一个简化示例是这样:

listener.tcp { bind = "0.0.0.0:1883" } websocket { enable = true bind = "0.0.0.0:8083" } auth = [ { login = "iot-user" password = "secret" } ]

注意不同版本的 auth 字段写法有差异,实际配置一定要以当前部署版本的官方文档为准。

3.3 gmqtt:把 MQTT 接入嵌到自己的 Go 服务里

gmqtt 是 Go 语言实现的 MQTT broker 库,Apache 2.0 许可,支持 MQTT 3.1.1 和部分 5.0 特性。它的核心价值在于它不是独立进程,而是可以像普通库一样被引入到你的业务服务里。

举个例子:

package main import ( "github.com/WiiBond/gmqtt" ) func main() { server := gmqtt.NewServer() listener, err := gmqtt.NewTCPListener(":1883") if err != nil { panic(err) } server.AddListener(listener) server.Run() }

真实项目里还需要处理 OnConnect、OnMessage 等 hook,做认证、消息持久化、权限校验。这种做法的好处是整个消息链路都在自己进程里,少一个独立的 broker 部署点;坏处是它本质上是一个协议库,不是完整产品,所有运维能力都要自己补。

gmqtt 最大的风险是维护力量薄弱,核心维护者基本是个人,遇到关键 bug 可能没人及时修。如果团队 Go 能力不错,愿意自己做兜底,它可以作为选型项;如果团队没有能力维护协议层代码,慎选。

3.4 自研协议接入层的边界在哪里

有时候甲方要求苛刻到不希望引入任何第三方 broker,那就只能自研协议接入层。MQTT 协议本身不算复杂,一个只支持 QoS 0 的简单接收入口,Netty 几百行关键代码就能跑通。但一旦要求完整支持 QoS 1/2、遗嘱、保留消息、会话恢复、共享订阅、MQTT 5.0 属性,工作量会指数级上升。

我见过不少团队低估这个工作量,觉得"反正协议规范就几十页",结果开发到会话状态管理阶段就开始返工。我的建议很直接:如果业务必须以最小化依赖交付,可以自研,但内核最好站在一个成熟的协议库上改造,不要从零写编解码。

3.5 一次讲清楚几个候选方案的功能差异

下面这张表是给选型会准备的,我整理得比较细,直接可以拿去跟团队讨论:

特性MosquittoEMQX 开源版NanoMQgmqtt
MQTT 3.1.1支持支持支持支持
MQTT 5.0支持支持支持部分支持
QoS 0/1/2支持支持支持支持
保留消息/遗嘱支持支持支持支持
共享订阅支持支持支持需确认
集群/高可用不支持,只能桥接支持部分版本支持不支持
规则引擎/数据集成不支持商业版为主Webhook/桥接不支持
WebSocket支持支持支持需自建
Dashboard简单
许可证EPL 2.0 / EDL 1.0Apache 2.0Apache 2.0Apache 2.0
国内团队主导
商业支持社区为主有企业版

做选型时,不需要每一列都对齐,抓住关键能力就够。我的判断标准是:要轻量、可替换、license 干净就选 NanoMQ;要完整平台能力、有商业兜底就继续用 EMQX;要嵌入现有服务就考虑 gmqtt;自研只适合少数特殊场景。

4. 迁移实操:从 Mosquitto 换到 NanoMQ,我踩过的配置与兼容性坑

4.1 为什么拿 NanoMQ 举例,而不是 gmqtt

因为绝大多数团队要替换的是"独立 broker",而不是把协议栈嵌进业务进程。NanoMQ 在定位上和 Mosquitto 最接近,都是轻量、单机、边缘友好,替换路径也最顺。gmqtt 更适合本身就在做定制开发的团队,那是另一个话题。

4.2 快速部署和配置迁移对照

如果原来用的是 Mosquitto,典型配置长这样:

port 1883 allow_anonymous false password_file /etc/mosquitto/passwd

迁到 NanoMQ 后,配置变成 HOCON 格式,auth 部分和监听器拆开写。这里最容易翻车的是密码文件不兼容。Mosquitto 的 passwd 文件是用 mosquitto_passwd 生成的哈希,格式和 NanoMQ 的 auth 配置不一样,直接把原文件搬过去是无效的,需要在 NanoMQ 里重新维护用户名密码。

配置好之后,先不要急着切生产。我会先做一轮最基本的消息收发验证:

mosquitto_pub -h localhost -p 1883 -t test/topic -m hello -q 1 mosquitto_sub -h localhost -p 1883 -t test/topic -v

这里只是一个最基础的验证,真正的坑在后面。

4.3 兼容性坑记录:我踩过的都写在这里

第一个坑是 WebSocket 默认关闭。 Mosquitto 可以在 listener 里直接开启 websockets 协议,NanoMQ 却需要在配置里显式把 websocket.enable 设为 true,再指定 bind 端口。如果前端 Vue3 项目用 mqtt.js 连接,经常会遇到 TCP 能连、WebSocket 连不上的情况,原因就是这里没开。

第二个坑是 ACL 语法完全不同。Mosquitto 的 acl_file 写法是 topic read 或 topic write 这样的模式,NanoMQ 用的是权限对象配置,没法直接迁移。如果原系统里有复杂的 ACL 规则,迁移时要重新设计权限模型。

第三个坑是 MQTT 5.0 的会话过期处理差异。两个 broker 对客户端没有设置 Session Expiry Interval 时的清理时机不一样,导致设备重连后订阅列表不一致。这个问题比较隐蔽,设备数量少的时候注意不到,设备量上来才会发现部分设备"丢订阅"。建议在迁移前规划好统一的会话过期参数。

第四个坑是日志格式不同。 Mosquitto 的日志偏 C 传统风格,字段相对固定;NanoMQ 的日志包含更多系统信息,一开始可能不习惯,排查问题时别按老经验找字段。

4.4 设备端和消息链路到底要不要动

好消息是,迁移 broker 通常不会动到设备端和消息链路,至少不会动到协议层。STM32 上移植的 MQTT 客户端,或者 4G 模块 EC20 的 AT 指令 MQTT 配置,只要把连接地址改成新 broker 的地址就行。Node-RED 里 OPC UA 转 MQTT 的流,只需要改 MQTT out 节点的 server 地址。Vue3 前端用 mqtt.js,注意 WebSocket path 是否要调整,NanoMQ 默认路径可能和 Mosquitto 不一样,这个要看文档确认。

唯一需要认真考虑的是,原来有没有用过 broker 自带的集成能力。比如 EMQX 规则引擎把消息转存到 Kafka 或数据库,如果原来依赖了这类能力,迁移到 NanoMQ 后就要自己实现消费端,或者用 NanoMQ 的桥接/Webhook 来对接。

5. 商用风险评估:许可证之外,还要看什么

5.1 今天的许可证不等于明天的许可证

许可证风险不是静态的,最大的变数是项目换了许可证。行业里不缺先例:Redis 从 BSD 转向 RSAL/SSPL,Elasticsearch 也从 Apache 2.0 转向 SSPL,MinIO 从 Apache 2.0 转向 AGPL。一旦你基于某个项目做了深度集成,上游换牌会让整个方案的合规基础崩塌。

所以评估国产替代方案时,我会重点看项目治理结构。Mosquitto 在 Eclipse 基金会,许可证变更需要基金会流程,相对稳定;NanoMQ 虽然由 EMQ 公司主导,但许可证明确是 Apache 2.0,而且版本快照可以自己保存,风险可控。比较实用的做法是,上线前把依赖的源码和 LICENSE 文件做一次快照存档,以后上游怎么变,都不影响当前版本的使用边界。

5.2 社区活跃度、供应链与二开成本

许可证只是门槛,过了门槛还要看项目能不能长期养得住。我在评估时会看几个指标:GitHub 提交频率、issue 平均响应时间、release 版本节奏、核心维护者数量。NanoMQ 有 EMQ 公司持续投入,更新节奏比较稳定;gmqtt 这类个人项目,如果维护者工作重心转移,项目可能进入沉默期。

供应链方面也不能忽视。Docker 镜像是否由官方构建、是否带签名、依赖组件有没有已知漏洞扫描报告,这些直接影响企业采购评审。信创类项目还会要求提供软著证书、第三方检测报告、国产操作系统和芯片适配证明,开源项目本身通常没有这些材料,需要找商业公司或自己送测。

二开成本也要想清楚。EMQX 是 Erlang OTP 生态,团队如果没有 Erlang 能力,二次开发基本无从谈起;NanoMQ 是 C++,改起来门槛也不低;gmqtt 是 Go,配合业务团队反而容易整合。

5.3 商用风险对照表:给选型会直接参考

我把几个方案放在一张表里对比,方便快速判断:

维度MosquittoEMQXNanoMQgmqtt
许可风险
维护风险中到高
国产化适配中到强
二开成本
长期演进稳定但慢功能持续更新边缘场景导向依赖个人
商业支持社区文档企业版支持企业支持可选

5.4 落地合规自查清单

如果你现在正在准备替换方案,建议照着这个清单逐项过一遍,基本能堵住大部分合规漏洞:

  1. 保留所有使用组件的 LICENSE 和 NOTICE 文件。
  2. 用扫描工具生成完整依赖 licenses 清单。
  3. 明确区分"独立进程使用"和"静态链接/嵌入使用",确认不触发 EPL 或 AGPL 义务。
  4. 对修改过的 EPL/AGPL 代码,提前准备源码交付物。
  5. 锁定版本,做代码快照,防止上游换牌。
  6. 商标使用注意别让甲方误以为你获得了官方认证。
  7. 信创类项目,提前准备软著、检测报告、适配证明三方材料。

这些内容不一定全都要用到,但每一项都可能在某个关键节点救你一命。

6. 我最后的选型建议

分享一个我自己实际用过、也推荐给朋友的处理方式。如果你的核心诉求是"替换 Mosquitto,要一个许可证干净、演进可控、长期能养住的轻量 broker",NanoMQ 是当前最稳妥的国产选择,Apache 2.0 许可在商用上没有历史包袱,EMQ 公司持续投入,出问题至少能找到人。如果你的团队本来就在 Go 服务里做深度定制,愿意承担协议库的维护成本,可以考虑 gmqtt,但一定要安排人长期盯它的社区动态。如果项目紧迫、预算充足、甲方需要全套商业支持和信创材料,EMQX 开源版仍是一个稳定选择,重点是提前和供应商确认哪些功能在企业版、哪些在开源版,白纸黑字写清楚。

最后再分享一个经验。替换 broker 本身不是大工程,真正让项目失控的是把"换 broker"和其他需求搅在一起。明明只是把 MQTT 接入点换掉,非要顺手升级 MQTT 5.0、顺手重构权限体系、顺手上个集群,看起来一步到位,实际上排查问题的时候根本分不清是新功能引入的 bug 还是迁移兼容性 bug。我建议卡死迁移范围:设备不改、业务不改、数据集成不改,只换 broker 内核,验证通过后再逐步做其他演进。把 license 扫描报告、版本快照和回滚脚本一起放进交付物,后面所有人都会感谢你。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询