VerneMQ 是一个用 Erlang/OTP 编写的高性能 MQTT 消息代理,专为大规模分布式部署设计。与单机版 Mosquitto 不同,VerneMQ 的多个节点可以组成一个逻辑集群,自动同步主题树、订阅关系和保留消息,从而在负载增加时通过水平扩展提高吞吐量,并在单个节点故障时保持服务可用。在 Debian 系统上部署 VerneMQ 集群,核心工作包括安装 Erlang 运行环境、通过官方软件源安装 VerneMQ、修改配置文件指定节点名称和集群发现方式,最后用 vmq-admin 命令将各节点连接起来。接下来会从环境准备开始,逐步说明每个环节的操作细节和常见问题。

安装 Erlang 与 VerneMQ 软件包
VerneMQ 运行在 Erlang 虚拟机上,因此第一步必须安装兼容版本的 Erlang。Debian 官方仓库中的 Erlang 版本较旧,建议使用 Erlang Solutions 或 Debian Backports 提供的新版本。以 Debian 12 为例,可以先更新系统并安装基础依赖,然后添加 VerneMQ 官方仓库。VerneMQ 提供了针对 Debian 的 deb 软件包,仓库地址为 https://vernemq.com/debian/,其中包含 GPG 签名。
添加仓库后,可以通过 apt 直接安装 vernemq。安装过程中会自动创建 vernemq 系统用户、目录结构和默认配置文件。默认配置下 VerneMQ 只会监听本机地址,还需要后续修改。安装完成后先不要启动服务,因为集群参数尚未配置。
# 更新软件包列表 sudo apt update sudo apt install -y gnupg2 curl # 添加 VerneMQ 仓库 GPG 公钥 curl -fsSL https://vernemq.com/debian/verne-mq-debian.gpg | sudo gpg --dearmor -o /usr/share/keyrings/vernemq-archive-keyring.gpg # 写入软件源配置 echo "deb [signed-by=/usr/share/keyrings/vernemq-archive-keyring.gpg] https://vernemq.com/debian/ bookworm main" | sudo tee /etc/apt/sources.list.d/vernemq.list # 更新并安装 sudo apt update sudo apt install -y vernemq
上述命令中的 bookworm 对应 Debian 12 的代号。如果使用 Debian 11,应替换为 bullseye。GPG 公钥通过 curl 下载并转换为二进制格式,保证软件包完整性。安装完成后,检查 Erlang 版本与 VerneMQ 的兼容性。VerneMQ 1.12 系列通常兼容 OTP 24/25,而 2.x 系列需要 OTP 25/26。如果版本不匹配,启动时会在日志中提示缺失模块。
安装过程中如果没有自动安装 Erlang,可以先手动安装 erlang-base、erlang-ssl、erlang-crypto 等包,或者使用 asdf 等版本管理工具安装完整 OTP 发行版。对于生产环境,建议保持所有节点的 Erlang 版本完全一致,否则分布式节点之间的 RPC 调用可能出现二进制不兼容问题。
配置节点名称与集群发现
VerneMQ 通过 Erlang 的分布式节点机制组建集群,每个节点必须具有唯一的节点名称,并且所有节点共享同一个分布式 cookie。节点名称格式为 name@host,通常由配置项 nodename 和 distributed_cookie 控制。打开 /etc/vernemq/vernemq.conf,将默认的 nodename = vernemq@127.0.0.1 改为实际主机名或 IP 地址,例如 vernemq@192.168.1.10。
集群发现有两种主要方式:静态列表和动态发现。对于小规模部署,使用静态列表最直接。在配置文件中添加 cluster_discovery = static 和 cluster_nodes = vernemq@192.168.1.10, vernemq@192.168.1.11,列出所有节点。动态发现可以基于 DNS 服务记录或 etcd,适合节点频繁变化的场景,但配置更复杂。
# /etc/vernemq/vernemq.conf 关键配置片段 nodename = vernemq@192.168.1.10 distributed_cookie = mysecretcookie listener.tcp.default = 0.0.0.0:1883 listener.ws.default = 0.0.0.0:8080 cluster_discovery = static cluster_nodes = vernemq@192.168.1.10, vernemq@192.168.1.11
distributed_cookie 必须是所有节点完全一致的字符串,任何不一致都会导致节点之间无法握手,表现为 vmq-admin cluster join 时出现 connection refused 或 not_allowed 错误。nodename 中的主机部分建议使用实际可解析的主机名或静态 IP,不要使用 127.0.0.1,否则其他节点无法寻址。
除了集群参数,还要注意 MQTT 监听地址。默认 listener.tcp.default 可能只绑定 127.0.0.1,需要改为 0.0.0.0 才能接受外部客户端的连接。如果使用 WebSocket,可以同时启用 listener.ws.default。配置完成后执行 sudo systemctl start vernemq 启动服务,并用 sudo journalctl -u vernemq -f 查看启动日志,确认没有报错。
使用 vmq-admin 组建集群并验证
当第一个节点正常启动后,第二个节点只需执行 vmq-admin cluster join 命令,指定集群中任意一个已存活节点即可加入。该命令会触发 Erlang 节点间的握手,并同步主题树和订阅表。示例中假设 192.168.1.10 是第一个节点,在 192.168.1.11 上执行加入操作。
# 在第二个节点上执行 sudo vmq-admin cluster join vernemq@192.168.1.10 # 查看集群状态 sudo vmq-admin cluster show # 输出示例 +--------------------+-------+ | Node |Running| +--------------------+-------+ |vernemq@192.168.1.10| true | |vernemq@192.168.1.11| true | +--------------------+-------+
如果 join 命令成功,cluster show 会列出所有节点且 Running 状态为 true。此时两个节点已经组成一个逻辑 broker,任何一个节点的 MQTT 客户端都能看到其他节点上发布的消息。验证时可以在节点 A 上订阅主题 test/topic,在节点 B 上发布消息,观察订阅者是否收到。
使用 mosquitto-clients 工具可以快速测试。在节点 A 的终端执行 mosquitto_sub -h 192.168.1.10 -t test/topic -d,在节点 B 的终端执行 mosquitto_pub -h 192.168.1.11 -t test/topic -m hello。如果收到消息,说明跨节点消息路由正常。VerneMQ 内部使用 Plumtree 广播协议传播元数据,并将消息通过主题树直接投递到订阅者所在的节点,不会经过中心转发节点,因此增加节点数量可以线性提升消息吞吐。
生产环境的关键注意事项
分布式 MQTT 集群的稳定性依赖于网络和配置的一致性。首先是防火墙端口:Erlang 分布式节点通信使用 EPMD 端口 4369 和一段动态端口范围,默认 9100-9109。这些端口必须在所有节点之间双向开放,否则 join 和心跳检测会失败。同时 MQTT TCP 端口 1883 和 WebSocket 端口 8080 需要向客户端开放。
其次,节点数量通常建议为奇数。VerneMQ 使用基于一致性哈希的分布式哈希表来存储保留消息和共享订阅状态,奇数个节点可以降低网络分区时产生脑裂的概率。生产环境建议至少 3 个节点。如果只有两个节点,一旦出现网络分区,双方都无法形成多数派,可能导致服务不可用。
# 开放集群相关端口(ufw 示例) sudo ufw allow 4369/tcp sudo ufw allow 9100:9109/tcp sudo ufw allow 1883/tcp sudo ufw allow 8080/tcp # 查看 VerneMQ 日志 sudo journalctl -u vernemq -n 100 --no-pager
日志和监控同样重要。VerneMQ 的日志默认输出到 systemd journal,也可以配置 file 日志。vmq-admin 提供多个查询命令,如 vmq-admin session show、vmq-admin retain show、vmq-admin plugin show,可用于排查客户端连接、保留消息和插件状态。对于生产环境,建议集成 Prometheus 监控指标,VerneMQ 原生支持 Prometheus 格式的 metrics 端点,便于观察集群的消息速率、连接数和队列长度。
最后,升级或重启节点时应逐个滚动进行。先将节点从集群中摘除,执行 vmq-admin cluster leave,然后停止服务、升级软件,再重新加入。一次性重启所有节点会导致主题树和订阅关系全部丢失,客户端需要重新订阅。通过逐步滚动升级,整套集群可以在不中断服务的情况下完成版本更新。