GroveMQ 项目图标
GroveMQ · MQTT Broker
Go · 消息中间件 · 开源

海量设备接进来,
消息照样送得到。

一个用 Go 写的 MQTT Broker,面向 AI、IoT、IIoT 和车联网场景。轻量级的 Actor 内核管理每个客户端会话,节点之间用 gRPC 自动路由消息,在 Kubernetes 里靠 headless service 自己找到同伴;TLS / ACL、持久会话、共享订阅和 Prometheus 指标都在里面。

Go 1.25+ MQTT 3.1.1 / 5.0 gRPC 集群 Kubernetes
grovemq / cluster · 3 nodes
node-1:1883publisher
node-2:1884subscriber
node-3:1885peer
PUBLISH sensors/veh-042/temp @ node-1
gRPC 路由 · 跨节点 ↓
SUBSCRIBER @ node-2 ✓ delivered
1883 MQTT 8081 gRPC 8082 /metrics
界面示意 · 端口与测试流程来自 README
订阅者不在同一节点,消息照样送得到
为什么

设备一多,
单节点 Broker 先撑不住。

会话、订阅和消息路由挤在一个进程里,扩容只能靠堆机器,跨节点投递还得自己补。

会话绑死在单机

客户端一重连,订阅状态就断档;离线期间的消息也没地方落。

集群要手工配

节点列表写死在配置里,K8s 里 Pod 一漂移就对不上,扩容得先改一遍配置。

出问题看不见

没有指标,连接数、Actor 重启次数基本靠猜,排查只能翻日志。

GroveMQ 用 Actor 管会话,把集群路由与节点发现交给独立的模块。

做了什么

从协议解析到集群发现,都在仓库里

pkg/ 下每个包管一件事,文档在 docs/ 里按角色分好了入口。

MQTT v3.1.1 / v5.0

CONNECT / SUBSCRIBE / PUBLISH 全流程,包含 MQTT 5.0 的 properties 与 reason codes。

Actor 并发内核

OTP 风格的轻量 Actor 管理每个会话,supervisor 按「let it crash」思路做容错重启。

动态集群

节点自动组成集群分担负载,跨节点消息路由由集群状态管理器自动处理。

K8s 原生发现

通过 headless service 自动发现 peer,Pod 漂移不用改节点列表。

gRPC 节点通信

Protobuf 强类型接口,承载路由、状态同步和集群管理三件事。

可观测与安全

Prometheus 指标(连接数、Actor 重启)、TLS、ACL、持久会话、retained 与共享订阅。

跑起来

三条命令,从单节点验到集群

需要 Go 1.25+;三节点集群示例还需要 Docker Compose v2。

1

构建

产出仓库根目录下的 grovemq 二进制,记得从仓库根目录启动,才能读到 config.yaml。

go build ./cmd/grovemq
2

启动单节点

1883 收 MQTT 连接、8081 走集群 gRPC、8082 暴露 /metrics。

./grovemq # localhost:1883 · :8081 · :8082
3

验跨节点投递

订阅者连 node-2 (1884)、发布者连 node-1 (1883),检查消息有没有送到对面。

./scripts/start-cluster.sh go run ./cmd/cluster-test
上线前

有几件事得先改

默认账号能直接上生产吗?

不能。config.yaml 里的 admin / admin123 是演示凭据,README 明确要求:暴露到任何网络之前,替换所有密码、关闭不需要的账号、复核 TLS 与 ACL 设置。测试套件也用同一套凭据,改了要同步。

怎么确认跨节点投递真的通?

cluster-test 把订阅者接到 node-2 (1884)、发布者接到 node-1 (1883),从 node-1 发一条消息,再看 node-2 的订阅者是否收到。Docker Compose 版直接用 docker-compose-cluster.yaml。

需要额外装数据库或注册中心吗?

不需要。会话存储是通用 KV 接口加内存实现,集群发现靠 K8s headless service,本地三节点用脚本或 compose 文件就能起。

从单节点到三节点集群,一条命令就能验

协议实现、集群路由、K8s 清单、混沌工程与 E2E 测试报告,都收在 docs/ 里。