这几年做物联网接入的项目,碰到不少团队在同一个问题上卡壳:服务端一直用 Mosquitto 或者 EMQX,功能、性能都没话说,但一到商业交付或者甲方验收阶段,就会有人跳出来问一句:“这开源协议,咱们商用到底合不合规?能不能换成国产自研的协议栈?”刚开始我还没太当回事,后来越来越多的项目因为许可证问题改方案、改代码,甚至推倒重来,我才意识到这个问题的分量一点不比选型本身轻。
这篇文章我就想从头梳理一下 MQTT 协议栈相关的国产替代思路:先讲清楚 Mosquitto 和 EMQX 的开源版权与商用风险到底藏在哪里,再把目前能纳入评估的国产方案摆出来对比,最后给出一套从国外开源栈迁移到国产栈的实操路径。无论你是做云平台的架构师,还是做边缘网关的嵌入式工程师,只要你的项目里用了 MQTT,这篇内容应该都能帮你少踩几个坑。
1. 为什么最近都在聊“国产 MQTT 协议栈”:一次商务评审引发的思考
1.1 MQTT 协议栈到底指什么,别把概念搞混了
聊国产替代之前,得先把“MQTT 协议栈”这个词拆明白。很多人一听到“协议栈”就想到 TCP/IP 协议栈那种跑在网卡驱动上的一整层软件,其实在物联网语境下,MQTT 协议栈通常包含三层含义:
第一层是协议规范本身,也就是 OASIS 发布的 MQTT 3.1.1 和 MQTT 5.0 标准文档,这层没有版权问题,谁都能照着实现。第二层是客户端库,比如 Eclipse Paho 系列、MQTT.js、NanoSDK 这些,它们负责设备端或者服务端应用去连接 broker,完成发布订阅、QoS 协商、心跳保活等动作。第三层是我们平时最常说的 broker 服务,也就是消息代理服务器,比如 Mosquitto、EMQX、NanoMQ,它们负责接收所有客户端连接,维护主题树,做消息路由,处理订阅关系和遗嘱消息。
做国产替代的时候,绝大多数人关心的是第三层 broker,因为它是整个消息链路的中枢,也是客户和技术评审最关注的部分。但第一层和第二层也会夹杂着许可证问题,后面我会专门讲。
1.2 Mosquitto 和 EMQX 为什么绕不开
既然要谈替代,首先得知道我们替代的到底是什么。Mosquitto 是 Eclipse 基金会下面的老牌开源项目,C 语言实现,以轻量著称,一个树莓派都能跑得很欢,非常适合边缘网关和嵌入式场景。EMQX 则是基于 Erlang/OTP 构建的高并发 broker,支持百万级连接、集群部署、规则引擎和数据集成,定位在云端集中接入层,是物联网平台最常选用的基础设施之一。
这两者在国内物联网项目里的存在感极高,以至于很多人形成了一个惯性思维:用 MQTT 就选 Mosquitto,要性能就上 EMQX。但在实际项目里,尤其是涉及企业采购、政府项目、车联网平台这类场景时,技术惯性敌不过合规审查。客户在选型表里会直接问:这个组件的开源许可证是什么?如果是国外社区主导的项目,你们有没有评估过供应链风险?如果对方要求提供国产化证明或者自主可控说明,Mosquitto 和 EMQX 就会显得比较被动。
1.3 国产化替代的三个驱动因素:合规、可控、服务
推动大家转向国产 MQTT 协议栈的,说白了是三个因素。第一个是交付合规,很多政企类项目在招标文件里就有明确的国产化清单要求,核心组件需要具备自主知识产权或者国内团队维护背景,这个因素在项目能不能中标这件事上起着决定性作用。第二个是代码可控,国外开源项目虽然代码公开,但版本演进方向、社区治理规则、安全公告响应速度都不受我们自己控制,万一哪一天上游项目调整许可证或者停止维护,下游会很被动。第三个是技术支持,国产开源项目背后通常有国内团队做社区维护和商业支持,出了问题能找到人,这一点对商业项目来说太重要了,开源软件最怕的就是遇到疑难问题没人管。
理解了这三点,接下来才能真正理解:替代 Mosquitto / EMQX,不只是换个软件包那么简单,而是要在许可证合规、功能兼容、长期维护三个维度上重新做一轮评估。
2. Mosquitto 与 EMQX 的开源许可证,商用风险到底在哪
2.1 Mosquitto 的 EPL 许可到底约束了什么
Mosquitto 的许可证是 Eclipse Public License 2.0(EPL-2.0)和 Eclipse Distribution License(EDL)双许可。听起来有点复杂,拆开就清楚了。
EPL 是一种弱 copyleft 许可证,它的核心逻辑是:如果你把 EPL 代码作为整体程序的一部分分发出去,并且你修改了 EPL 代码本身,那么你对 EPL 代码部分所做的修改,必须以 EPL 许可证再授权给用户。换句话说,你可以直接把 Mosquitto 集成到你的商业产品里,甚至可以不公开你的商业代码,但前提是你不改动 Mosquitto 源码,或者即使改动了,也要把改动的那部分按 EPL 开源。这里说的“分发”是关键,如果只是在公司内部服务器上跑,不分发给第三方,EPL 一般不强制你开源改动。
至于 EDL,它本质上是一个类 BSD 的宽松许可证,主要适用于 libmosquitto 这个库。也就是说,你在自己的应用里调用 libmosquitto 做客户端逻辑,用 EDL 授权部分是没有传染性的,可以放心闭源。
所以 Mosquitto 的商用风险不在“不能用”,而在“用了之后不清楚边界在哪里”。我见过不少团队直接 fork 了 Mosquitto 源码,在里面加了自己的鉴权逻辑、数据库插件,然后打包成公司私有 broker 对外提供商业服务,这种情况下,如果对方索要源码,他们其实是负有 EPL 开源义务的。这种事一旦被深究,轻则违约,重则影响产品上市节奏。
2.2 EMQX 的 Apache 2.0 好在哪里,隐藏风险是什么
EMQX 开源版的许可证是 Apache License 2.0,这个许可证对商业使用非常友好。它允许你自由使用、修改、分发,包括闭源分发,前提是你保留原始的版权声明和 NOTICE 文件。相比 EPL,Apache 2.0 的传染性弱得多,你修改过的代码不强制开源。
但是 EMQX 场景下有两个隐藏风险点。
第一个是开源版和企业版的边界问题。EMQX 的核心 broker 是开源的,但企业版里包含的规则引擎扩展、数据集成连接器、多租户管理等很多功能是商业付费的。如果你的项目里通过某种方式使用了这些商业功能,却没有购买授权,这在法律层面就构成了违约。实际项目里尤其容易踩线的是:从开源版仓库里直接拉代码,然后自己编译开启了企业版才有的功能模块,这种做法风险相当高。
第二个是依赖组件的许可证传染问题。Apache 2.0 只保护 EMQX 项目自身的代码,不保护它依赖的第三方库。EMQX 是一个庞大的系统,依赖了 Erlang 生态里的大量第三方库,有些库可能采用 GPL 或 AGPL 这类强 copyleft 许可证。如果这些依赖是以“动态链接”或者“独立进程通信”方式集成的,争议空间还比较大,但如果以“静态链接”方式打进了二进制,在某些司法管辖区的解读里,整个派生作品都可能被传染。这也是为什么大厂做开源合规时,一定要做软件物料清单(SBOM)扫描,就是要把每一条依赖的许可证都查得明明白白。
2.3 开源版权自查最容易忽略的三个地方
在做 MQTT 开源版权自查的时候,有三个方面最容易被项目组忽略。
第一个是客户端库的许可证。很多人只盯着 broker,觉得 broker 没问题就万事大吉,实际上设备端用的 Paho、嵌入式端用的各种 MQTT 库,同样有自己的许可证。比如 Eclipse Paho 的 C 库是 EPL/EDL 双许可,如果用 EPL 授权方式改了源码,同样会触发开源义务。
第二个是 Docker 镜像的合规性。大家习惯了从 Docker Hub 拉镜像一把梭,但镜像里打包的操作系统基础层、运行库、配置工具,每一项都有独立许可证。你在交付物里如果包含了这些镜像,等于把里面的所有许可证都带了进去。
第三个是修改记录和版权声明的保留。Apache 2.0 和 EPL 都要求保留原始版权声明,很多团队 fork 代码后直接删了 LICENSE 文件或者改了版权注释,这个问题一旦被发现,就算你没有其他违规,光这一点就能被判定为侵权。
2.4 风险级别对照表
| 使用方式 | Mosquitto (EPL/EDL) | EMQX 开源版 (Apache 2.0) | 风险等级 |
|---|---|---|---|
| 内部部署,不分发给第三方 | 允许,修改无需开源 | 允许,修改无需开源 | 低 |
| 作为产品分发,未修改原项目 | 允许,需保留许可证 | 允许,需保留许可证 | 低 |
| 修改源码后作为商业产品分发 | 修改部分必须以 EPL 开源 | 允许闭源,需注明修改 | 中高 |
| 使用商业版功能但未购买授权 | 不涉及 | 构成违约 | 高 |
| 依赖中混入 GPL/AGPL 组件 | 可能传染 | 可能传染 | 高 |
这个表格不是我拍脑袋写的,它反映了开源许可证在实际商业交付中最常见的红线。我个人建议,但凡项目要对外交付,都得拿着这个维度再过一遍。
3. 哪些国产方案可以纳入评估:NanoMQ、GMQTT 与物联网平台内置 broker
3.1 NanoMQ:目前最适合“平替”EMQX 的国产开源方案
先说结论:如果你需要一个能真正扛住生产流量的国产 MQTT broker,NanoMQ 是目前最成熟的选项之一。
NanoMQ 是 EMQ(也就是 EMQX 背后的公司)推出的开源 MQTT 消息服务,代码用 C 语言编写,底层基于 NNG 异步 I/O 库,许可证是 Apache 2.0,由国内团队主导社区维护,文档和 issue 反馈都是中文优先。这里有个有意思的点:EMQ 一边维护着 EMQX,一边又做了 NanoMQ,这两者定位是有差异的。EMQX 走的是 Erlang/OTP 大集群路线,适合云端海量连接;NanoMQ 走的是轻量高性能路线,更强调边缘侧部署、资源占用小、启动速度快。
从功能上看,NanoMQ 支持 MQTT 3.1.1 和 5.0,支持 TCP/TLS/WebSocket 接入,支持 QoS 0/1/2、遗嘱消息、保留消息、共享订阅,还内置了消息持久化和简单的规则处理能力。对于大多数中小型物联网项目来说,替换 EMQX 时功能上是够用的。更实用的一点是,NanoMQ 的配置风格和 Mosquitto 有相似之处,从 Mosquitto 迁移过去的学习成本很低,后面我会专门演示。
3.2 GMQTT 与自研嵌入式协议栈的适用场景
GMQTT 是一个 Go 语言实现的 MQTT broker 库,许可证为 MIT,作者和主要贡献者里有不少国内开发者。它和 NanoMQ 的定位不太一样:NanoMQ 是开箱即用的 broker 服务,GMQTT 更偏向于一个协议组件,开发者可以把它的 server 能力嵌到自己的 Go 服务里,对外提供 MQTT 接入端口。
这种方式的优势是定制性极强,你可以直接在自己的业务进程里处理 MQTT 消息,省掉一层网络转发;缺点是需要自己承担稳定性保障,比如连接管理、心跳超时、消息堆积、集群扩展这些能力都要自己补。所以 GMQTT 更适合那些有较强 Go 开发能力、并且 MQTT 只是作为业务系统一个子模块的场景,而不是想直接换掉一个基础设施服务的情况。
至于嵌入式端的国产协议栈,很多 4G 模组、蓝牙模组、Wi-Fi 模组出厂的时候就已经内置了 MQTT 协议实现,比如通过 AT 指令集直接完成 MQTT 连接和消息收发。这种方式不算“自研”,但对设备厂商来说是最省心的国产化方案,不存在把自己的代码和第三方开源库绑在一起的问题。真正需要自己移植的,往往是 STM32 这类 MCU 平台,常见做法是在 lwIP 基础上实现一套轻量 MQTT client,或者基于 NanoSDK 这类国产库做裁剪。
3.3 国产物联网平台中内置 MQTT broker 的选型
还有一个容易被忽略的方向:直接用国产物联网平台充当 MQTT 接入层。比如 JetLinks、DG-IoT、FastBee 这类国内开源的物联网基础平台,普遍内置了 MQTT broker 能力,设备接入、消息路由、数据存储、设备管理都在一个系统里完成,而不是像 EMQX 那样只提供一个消息管道,还要自己去搭配数据库和业务服务。
这种方案的好处是“替代”的粒度更大,不只是替换 broker,而是把整个设备接入层都收编进来,客户看到的技术栈里 MQTT 只是其中一个模块,核心知识产权在平台本身。坏处是如果你的项目已经有一套成熟的业务系统,只缺 MQTT 接入能力,引入一个完整平台就显得太重了,还要承担平台本身的升级维护负担。所以这个方案更适合新项目立项,而不是老项目迁移。
3.4 决定“开源改造”还是“完全自研”的评估方法
每次聊到国产替代,总会有人问:我能不能完全自研一套 MQTT broker?我的回答一贯是:能,但先回答三个问题。
第一,你的团队有没有能力处理 MQTT 协议的各种边界情况?MQTT 看着简单,真正实现起来,会话恢复、QoS 2 的消息去重、遗嘱消息的精确时序、保留消息和订阅重叠的处理,每一个都是细节密集的活,稍微疏忽就在高并发下出问题。第二,你愿不愿意长期投入维护?broker 不是写完就能丢的功能,要持续跟协议修订、安全补丁、性能优化保持同步,这个人力成本是持续的。第三,你的业务真的需要自研吗?如果只是出于合规要求,选择国产开源项目完全能覆盖;只有当你对 broker 有深度定制的诉求,且团队能承担长期投入时,自研才划算。
我个人的判断标准是:业务功能能用开源解决的,绝不自己写核心通信层;必须自己写的,只在开源实现上面做一层封装,把容易变动的业务逻辑和底层协议剥离开。这套逻辑,在我做的几个设备接入项目里都走得通。
4. 从 Mosquitto / EMQX 迁移到国产协议的实操步骤
4.1 迁移前先做功能对照,别急着换服务
很多人拿到“国产替代”的任务,第一反应是赶紧把服务换掉,这是最容易翻车的做法。MQTT broker 虽然在协议层面是兼容的,但每个产品都有自己额外的功能集。EMQX 有强大的规则引擎、数据桥接、HTTP API、共享订阅、延迟消息,NanoMQ 的规则处理能力相对轻量,如果你原本重度依赖 EMQX 的规则引擎做消息流转,迁移前必须先列一张功能对照表。
我建议用一张表格把当前项目的关键功能逐项列出来:是否用了 QoS 1/2、是否用了 MQTT 5.0 的 user property、是否用了共享订阅、是否用 HTTP API 做客户端管理、是否用了数据持久化、是否有集群需求、是否需要 TLS 双向认证。每一项都要标注“必须支持”还是“可以降级”,然后拿这个列表去对比候选国产方案的功能矩阵。这一步没有捷径,但做好了,后面迁移就是体力活。
4.2 部署替换示例:Mosquitto 迁移到 NanoMQ
直接上一个最实际的例子:假设原来你是在一台边缘服务器上用 Docker 跑 Mosquitto,现在要替换成 NanoMQ。
原来的 Mosquitto Docker 启动命令大致是这样的:
docker run -d --name mosquitto \ -p 1883:1883 \ -p 9001:9001 \ -v /etc/mosquitto/config:/mosquitto/config \ -v /etc/mosquitto/data:/mosquitto/data \ eclipse-mosquitto:2.0对应的配置里通常有监听端口、允许匿名访问、持久化设置这些参数,比如:
listener 1883 allow_anonymous true persistence true persistence_location /mosquitto/data/换成 NanoMQ 之后,Docker 启动方式变成:
docker run -d --name nanomq \ -p 1883:1883 \ -p 8083:8083 \ -p 8883:8883 \ -e NANOMQ_BROKER_URL="nmq-tcp://0.0.0.0:1883" \ emqx/nanomq:latestNanoMQ 的完整配置支持放在/etc/nanomq.conf里,关键项是这样:
broker { url = "nmq-tcp://0.0.0.0:1883" url = "nmq-tls://0.0.0.0:8883" } http_server { url = "0.0.0.0:8083" } sqlite { enable = true } log { to = ["file", "console"] level = info }可以看到,两者的监听端口和基本配置思路很接近,迁移成本主要在协议细节的对照上。Mosquitto 的allow_anonymous true对应 NanoMQ 里要显式设置鉴权规则,Mosquitto 的持久化目录对应 NanoMQ 的 SQLite 持久化配置。这个阶段最好先在一个隔离环境里跑起来,让原本的客户端都连上来做冒烟测试,再考虑切换生产流量。
4.3 客户端库与设备端适配
broker 换掉以后,客户端这边通常不用大改,因为 MQTT 协议本身是标准化的,客户端只关心 broker 的 IP、端口、用户名密码和主题,不关心 broker 是谁实现的。但有几个细节要注意:如果原来用的是 EMQX 提供的专用客户端 SDK,比如某些语言里为 EMQX 量身定制的 API 封装,那就需要评估是不是可以换成通用的 MQTT 客户端库。
嵌入式设备端也一样,原来的 STM32 项目里如果移植的是某个特定 broker 的 client 库,最好确认它支持标准 MQTT 3.1.1/5.0,支持 TCP,支持 TLS,这三个条件满足,从 Mosquitto 换到 NanoMQ 基本不用动设备程序。真正需要改的,往往是 TLS 证书链的配置,因为换 broker 之后证书也可能跟着换,设备端要把新 CA 证书刷进去。
4.4 压测验证与上线切换策略
替换后的验证环节,我建议至少做三层:连通性测试、QoS 功能测试、压力测试。
连通性测试最简单,用 MQTT X 或者 mosquitto_pub/mosquitto_sub 直接连新 broker 发布订阅一个测试主题就行。QoS 测试要覆盖 QoS 0/1/2 三种级别,重点是 QoS 2 的消息是否会出现重复或者丢失。压力测试可以用 emqtt-bench 这类工具,比如模拟两万个客户端同时连上来,持续发布消息,观察 broker 的 CPU、内存、消息延迟和丢包率。
emqtt_bench sub -h broker_ip -p 1883 -c 20000 -t test -q 1 emqtt_bench pub -h broker_ip -p 1883 -c 2000 -t test -q 1 -m '{"ts":1700000000}'这套命令只是示例,实际压测要根据项目规模调整参数。真正上生产的时候,我强烈建议先让一部分测试设备切到新 broker,观察几天,确认稳定后再全量切换。毕竟 MQTT 链路出了问题,设备端掉线,业务影响面是很大的。
5. 版权合规与商用落地避坑记录
5.1 最常见的四个认知误区
做开源版权合规这么几年,我见过太多团队在同一个误区里打转。这里把最容易踩翻车的四条整理出来。
误区一:“开源就是免费随便用。”这个是最常见的误解,开源指的是源代码开放,不是放弃版权。每个开源项目都有自己的许可证,决定了你能怎么用、怎么改、怎么分发。
误区二:“我是用动态链接,所以 GPL 不传染。”这个说法在技术圈流传很广,但法律上和实务上都没那么绝对。动态链接在部分司法管辖区依然可能被视为组成派生作品,特别是当你拿 GPL 库提供核心服务时,风险更高。别拿自己的商业项目赌这个。
误区三:“我改了代码但只是自己内部用,不对外分发就没事。”对 EPL 这类弱 copyleft 来说,内部使用确实一般不构成分发,但如果你以 SaaS 方式对外提供服务,也就是由用户通过网络访问你的系统,部分许可证在这个场景下会触发开源义务,这个需要仔细看条款。
误区四:“换了国产开源项目,许可证问题就自动消失了。”这个也站不住脚,国产开源项目同样有许可证,Apache 2.0、MIT、BSD 算宽松的,但也有用 GPL 的国产项目,选型时还是要看许可证,不能只看“国产”两个字。
5.2 我把 Mosquitto 二次开发后交付客户,到底会不会出事
这是个高频问题,我用一个简化案例讲清楚。假设你基于 Mosquitto 修改了源码,增加了一组私有 API 和数据库联动逻辑,然后把这个定制版 broker 作为产品的一部分卖给了客户。按照 EPL-2.0 的条款,你修改过的 Mosquitto 部分必须以 EPL 许可证提供给客户,客户拿到后有权继续修改和再分发。这不是说你的整个产品都要开源,而是说 Mosquitto 这个组件以及你对它的修改,必须保持开源。
如果你实在不想开源这部分改动,那从一开始就应该走另一条路:不要直接改动 Mosquitto 源码,而是把 Mosquitto 作为一个独立进程部署,你的私有逻辑全部做成外部模块,通过 MQTT 协议而不是代码修改与它通信。这种情况下,你用的是进程间通信,不是代码级修改,触发传染义务的概率就低得多。当然,这只是实操层面的经验参考,具体项目还是建议咨询专业的知识产权律师。
5.3 给团队落地的三条合规建议
第一,从项目第一天就把许可证清单维护起来。不管用的是 Mosquitto、EMQX 还是 NanoMQ,把项目里所有开源依赖的许可证、版本、版权声明、修改记录都记录在同一份文档里,后续做合规审计的时候这份清单就是你的护身符。
第二,能用宽松许可证的组件,就不要引入强 copyleft 的。同样是 MQTT broker,Apache 2.0 和 MIT 的集成成本远低于 EPL 和 GPL。这个原则在选型阶段就要定下来,而不是等代码写完了再反推调整。
第三,对外交付物里必须保留 LICENSE 和 NOTICE。很多项目打包时只留了可执行文件,把开源组件的许可证目录给漏了,这在合规审查时是非常低级的失误,明明可以避免。
5.4 个人实操中踩过的几个坑
最后分享几个我自己真实踩过、也帮别人填过的坑,希望能帮大家省点时间。
第一个坑是客户端库的许可证盲区。很早之前我在一个网关项目里用了某个 MQTT 客户端库,当时只关注了 broker 的许可证,没有深究客户端库的情况。后来客户做法务尽调,发现那个库是 GPL 授权的,整个网关固件的合规解释变得非常被动,最后只能临时替换客户端库,白白耽误了两周工期。这件事之后,我要求项目里任何一个第三方依赖都必须做许可证登记。
第二个坑是 EMQX 的规则引擎依赖。有一次做迁移评估,客户说他们只是想从 EMQX 换到国产方案,结果一聊发现,他们的整个数据处理链路都挂在 EMQX 规则引擎上,包括消息格式转换、设备在线状态计算、告警触发。这种场景迁移过去,光是把规则逻辑改写到另一个实现就够写两周代码了。所以我现在评估替代方案时,第一件事就是确认项目是否重度使用了 broker 的增值功能,而不是只盯着协议栈本身。
第三个坑是 TLS 证书更新。MQTT 走 TLS 的时候,broker 换掉,证书链也要跟着换,设备端如果做了证书固定,就得挨个去更新设备固件。边缘侧设备动辄几百上千台,更新固件本身就是个不小的工程。所以切换 broker 之前,一定要先确认设备端是不是能远程升级、证书更新方案是什么样的,否则技术方案再完美也可能卡在运维环节。
做了这么多 MQTT 相关项目,我个人的体会是:替代 Mosquitto 和 EMQX,真正难点不在协议栈本身,而在你现有的系统到底和 broker 绑得有多深。纯做消息转发,迁移非常平滑;深度依赖了 EMQX 的规则引擎、数据集成,迁移就得连带处理业务代码。国产方案的价值,更多体现在合规确认和技术支持上,而不是说换上之后就能一劳永逸。最后再给一条实在的建议:不管你选 NanoMQ 还是别的方案,先把许可证清单、功能对照表、压测报告这三样东西做齐了,再拿去和客户谈国产化替代,你会发现整个项目都顺很多。