EMQX 5.0 生产级集群部署最佳实践 (Docker Compose)
前言:为什么生产环境需要 EMQX 集群?
在正式的生产环境中,单一服务节点是脆弱的,它无法抵御硬件故障或流量激增带来的风险。“集群” 是构建一个健壮、可靠系统的基石。通过将多个 EMQX 节点组成集群,您的业务将获得:
- 极致的高可用性: 单个节点宕机,其他节点能无缝接管,业务不中断。
- 强大的水平扩展能力: 面对海量设备连接和消息洪流,只需向集群中添加新节点即可线性提升系统容量。
- 简化的运维管理: 在集群任意节点上,都可以查看和管理整个集群的状态。
本指南将作为一份权威的最佳实践,手把手带您使用 Docker Compose 在多台服务器上构建一个真正稳定、高效、可扩展的 EMQX 5.0 生产级集群。
一、规划您的部署
在动手之前,合理的规划是成功的关键。请根据您的业务需求,评估以下几点。
1. 版本选择
- EMQX 版本: 本指南基于 EMQX 5.0 及更高版本。EMQX 5.0 对集群架构进行了重大升级,与 4.x 版本不兼容。
- 镜像标签: 我们强烈建议您使用明确的、最新的稳定版标签,例如
emqx/emqx:5.7.2,而不是latest。这可以保证集群中所有节点的版本完全一致,并避免因自动更新导致的不确定性。 - 版本一致性: 集群中的 所有节点都必须使用相同版本 的 EMQX 镜像,例如,所有节点都应为 5.7.2 版本,不能混合使用 5.7.1 和 5.7.2。
2. 硬件与网络要求
硬件配置直接影响集群的性能和容量。以下是基于典型场景的建议:
以下数据展示了在特定场景下,单个 EMQX 节点所能承载的连接数及其对应的硬件配置。在规划集群时,您可以将集群的总容量视为各个节点容量的总和。
| 配置类型 | CPU (vCore) | 内存 (RAM) | 磁盘 | 适用场景 |
|---|---|---|---|---|
| 最低推荐 | 2 核 | 4 GB | 20GB SSD | 开发、测试、小型生产项目 (万级连接) |
| 标准生产 | 4 核 | 8 GB | 50GB+ SSD | 中型生产项目 (十万到百万级连接) |
| 大规模生产 | 8+ 核 | 16+ GB | 100GB+ SSD | 大规模、高吞吐量项目 (百万级以上连接) |
网络要求 (至关重要):
- 低延迟、高带宽: 集群节点之间需要频繁地进行心跳检测和数据同步。请确保节点部署在同一个数据中心或 VPC 内,网络延迟应 低于 10ms。
- 网络隔离: 生产环境的服务器应部署在安全的内网中,仅对外暴露必要的服务端口。
二、环境准备:打造稳固的基石
在开始部署之前,请确保所有计划加入集群的服务器上都已安装好以下两个核心工具:
- Docker:一个轻量级的“集装箱”技术,确保 EMQX 在任何服务器上都拥有一致的运行环境。
- Docker Compose:一个强大的“集装箱编排工具”,让我们能通过一个简单的配置文件,轻松定义和管理 EMQX 服务。
步骤 1:安装 Docker 和 Docker Compose
我们提供两种安装方式:官方分步安装和一键脚本安装。
方式一:官方推荐安装(最稳定)
我们 首要推荐 您遵循 Docker 官方文档进行安装,这是最安全、最稳定的方法,可以确保您获得最新的特性和安全更新。
-
安装 Docker Engine:
-
安装 Docker Compose:
# 从官方 GitHub Release 页面下载最新稳定版 sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 授予执行权限 sudo chmod +x /usr/local/bin/docker-compose
方式二:一键脚本安装(国内用户推荐)
如果您在国内服务器上操作,或者觉得官方步骤比较繁琐,可以使用以下由国内镜像源提供的一键安装脚本。它可以自动为您完成 Docker 和 Docker Compose 的安装,非常便捷。
# 执行此命令将自动安装 Docker 和 Docker Compose
bash <(curl -sSL https://linuxmirrors.cn/docker.sh)
⚠️ 安全须知
这种
curl | bash的方式意味着您将直接下载并以管理员权限执行来自第三方服务器的脚本。请确保您信任脚本的来源 (linuxmirrors.cn)。对于安全性要求极高的生产环境,我们依然建议您优先选择方式一,通过官方渠道进行安装。
步骤 2:验证安装
无论您使用哪种方式安装,最后都需要进行验证。在每台服务器的终端中执行以下命令,如果能成功返回版本号,则代表您的环境已准备就绪。
docker --version
# 预期输出: Docker version xxx, build ...
docker-compose --version
# 预期输出: Docker Compose version xxx
三、核心架构:构建多主机高可用集群
我们的目标是在两台或多台独立的服务器上构建一个真正的高可用集群。
关键架构决策:host 网络模式
我们将使用 Docker 的 host 网络模式。这意味着容器将不再拥有独立的内部 IP,而是直接共享宿主机的网络,对外暴露的就是服务器的真实 IP 地址。
为什么选择 host 模式?
- 性能最优: 网络通信无额外开销,接近裸机性能。
- 配置最简: 无需复杂的网络配置,节点间可以直接通过服务器 IP 发现和通信,非常直观。
- 稳定性高: 这是经过生产环境广泛验证的、最可靠的 Docker 集群组网方案之一。
⚠️ 关键前提:配置防火墙
这是部署过程中最容易出错的一步! 为了确保集群正常工作,您必须配置防火墙(或云服务商的安全组),放行以下端口的访问规则:
集群内部通信端口 (节点之间必须互通):
| 端口 | 协议 | 源地址 (Source) | 目标地址 (Destination) | 用途说明 |
|---|---|---|---|---|
4370 | TCP | 集群内任一节点 IP | 集群内所有其他节点 IP | epmd 端口,用于 Erlang 节点服务发现。 |
5370 | TCP | 集群内任一节点 IP | 集群内所有其他节点 IP | EMQX 5.x 节点间 RPC 和数据同步的核心端口。 |
对外服务端口 (根据需要对客户端或管理员开放):
| 端口 | 协议 | 源地址 (Source) | 目标地址 (Destination) | 用途说明 |
|---|---|---|---|---|
1883 | TCP | 0.0.0.0/0 (或指定客户端 IP) | 所有节点 IP | 默认的 MQTT 服务端口。 |
8883 | TCP | 0.0.0.0/0 (或指定客户端 IP) | 所有节点 IP | TLS/SSL 加密的 MQTT 服务端口。 |
18083 | TCP | 0.0.0.0/0 (或指定管理员 IP) | 所有节点 IP | EMQX Dashboard HTTP 管理控制台端口。 |
四、部署实践:构建与扩展集群
我们将以一个典型的三节点集群为例,它兼具高可用性和良好的扩展性。在生产环境中,推荐使用奇数个节点(如 3, 5, 7),这有助于在网络分区等极端情况下维持集群的决策一致性。
- 服务器 A (节点1): IP 地址为
192.168.0.240 - 服务器 B (节点2): IP 地址为
192.168.0.188 - 服务器 C (节点3): IP 地址为
192.168.0.189
步骤 1: 部署初始节点
在 服务器 A, B, C 上分别创建 docker-compose.yml 文件。
在 服务器 A, B, C 上分别创建 docker-compose.yml 文件。这三个文件的内容几乎完全一样,唯一的区别在于 EMQX_NODE__NAME 环境变量的值。
文件 1: 在服务器 A (192.168.0.240) 上创建 docker-compose.yml
version: '3.8'
services:
emqx-node: # 服务名称统一,方便管理
image: emqx/emqx:5.7.2 # 使用明确的版本号
container_name: emqx # 容器名称统一
restart: always
network_mode: "host"
environment:
# 唯一的不同点:节点名称必须设置为当前主机的IP地址
- EMQX_NODE__NAME=emqx@192.168.0.240
# --- 以下配置在所有节点上必须完全相同 ---
- EMQX_NODE__COOKIE=YourStrongSecretCookie # 生产环境请使用更复杂的Cookie
- EMQX_CLUSTER__DISCOVERY_STRATEGY=static
# 最佳实践:SEEDS 列表包含所有成员,且在所有节点上保持一致
- EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.0.240,emqx@192.168.0.188,emqx@192.168.0.189
volumes:
- ./data:/opt/emqx/data
- ./log:/opt/emqx/log
文件 2: 在服务器 B (192.168.0.188) 上创建 docker-compose.yml
version: '3.8'
services:
emqx-node:
image: emqx/emqx:5.7.2
container_name: emqx
restart: always
network_mode: "host"
environment:
# 唯一的不同点:节点名称必须设置为当前主机的IP地址
- EMQX_NODE__NAME=emqx@192.168.0.188
# --- 以下配置在所有节点上必须完全相同 ---
- EMQX_NODE__COOKIE=YourStrongSecretCookie
- EMQX_CLUSTER__DISCOVERY_STRATEGY=static
- EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.0.240,emqx@192.168.0.188,emqx@192.168.0.189
volumes:
- ./data:/opt/emqx/data
- ./log:/opt/emqx/log
文件 3: 在服务器 C (192.168.0.189) 上创建 docker-compose.yml
version: '3.8'
services:
emqx-node:
image: emqx/emqx:5.7.2
container_name: emqx
restart: always
network_mode: "host"
environment:
# 唯一的不同点:节点名称必须设置为当前主机的IP地址
- EMQX_NODE__NAME=emqx@192.168.0.189
# --- 以下配置在所有节点上必须完全相同 ---
- EMQX_NODE__COOKIE=YourStrongSecretCookie
- EMQX_CLUSTER__DISCOVERY_STRATEGY=static
- EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.0.240,emqx@192.168.0.188,emqx@192.168.0.189
volumes:
- ./data:/opt/emqx/data
- ./log:/opt/emqx/log
提示: 服务器 B 和 C 的配置与 A 的配置几乎完全相同,您只需将
EMQX_NODE__NAME的值修改为各自服务器的 IP 即可。SEEDS列表在所有节点上都应保持一致,无需更改。
步骤 2: 启动与验证集群
在 所有服务器上分别执行 以下操作:
-
准备数据目录
mkdir -p data log sudo chown -R 1000:1000 ./data ./log -
启动 EMQX 节点 (建议逐个启动,间隔30秒)
docker-compose up -d -
验证集群状态
等待约 1 分钟后,在 任意一台服务器 上执行检查命令:docker exec emqx-node1 emqx ctl cluster status您应该能在
Running Nodes列表中看到所有三个节点的名称。
步骤 3: 扩展现有集群 (添加新节点)
随着业务增长,您可能需要向现有集群中添加新节点。假设我们现在要添加 服务器 D (节点4),其 IP 地址为 192.168.0.190。
-
更新所有现有节点的配置
这是最关键的一步!您必须登录到 服务器 A, B, C,修改各自的docker-compose.yml文件,将新节点emqx@192.168.0.190添加到EMQX_CLUSTER__STATIC__SEEDS列表中。例如,服务器 A 的配置应更新为:
# ... 其他配置 ... environment: # ... 其他环境变量 ... # 将新节点 D 添加到包含所有成员的种子列表 - EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.0.240,emqx@192.168.0.188,emqx@192.168.0.189,emqx@192.168.0.190 -
为新节点创建配置
在新的 服务器 D (192.168.0.190) 上创建docker-compose.yml,其SEEDS列表应与更新后的其他节点 完全一致。# 服务器 D 的配置 # ... environment: - EMQX_NODE__NAME=emqx@192.168.0.190 - EMQX_NODE__COOKIE=YourStrongSecretCookie - EMQX_CLUSTER__DISCOVERY_STRATEGY=static - EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.0.240,emqx@192.168.0.188,emqx@192.168.0.189,emqx@192.168.0.190 # ... -
应用变更并启动新节点
- 在 服务器 A, B, C 上,依次执行以下命令以应用配置变更(滚动更新):
docker-compose down && docker-compose up -d - 在新的 服务器 D 上,执行启动命令:
# 准备目录 mkdir -p data log && sudo chown -R 1000:1000 ./data ./log # 启动 docker-compose up -d
- 在 服务器 A, B, C 上,依次执行以下命令以应用配置变更(滚动更新):
-
最终验证
稍等片刻,在任意节点上再次检查集群状态,您应该能看到全部四个节点都已成功加入。
五、运维与管理:修改配置与数据安全
部署完成后,日常运维是保障系统稳定运行的关键。以下是关于修改配置和数据管理的最常见问题。
1. 修改 docker-compose.yml 文件后如何生效?
答案:必须重启服务容器。
对 docker-compose.yml 的任何修改(例如更改环境变量、更新镜像版本)不会自动应用到正在运行的容器上。您需要按以下步骤操作:
-
停止并移除旧容器: 在
docker-compose.yml所在目录执行:docker-compose down这个命令只会移除容器,并不会删除 Docker 这个软件本身。
-
基于新配置创建并启动新容器:
docker-compose up -dDocker Compose 会读取您修改后的配置,创建并启动符合新配置的容器。
2. 更新配置会丢失数据吗?—— 持久化的重要性
答案:只要您正确使用了卷(Volumes),数据就不会丢失。
- 数据安全: 在我们的
docker-compose.yml示例中,通过volumes配置项将容器内的/opt/emqx/data和/opt/emqx/log目录映射到了宿主机的./data和./log目录。这意味着所有关键数据(如配置、Mnesia 数据库等)都保存在您的服务器硬盘上,而不是临时的容器里。 docker-compose down的行为: 默认情况下,docker-compose down只会删除容器,它不会触碰您通过volumes映射的数据卷。因此,当您用docker-compose up -d启动新容器时,它会重新挂载到这些已存在的目录,所有数据都会被完整保留。
⚠️ 高危操作警告
绝对不要随意使用
docker-compose down -v命令。-v参数会告诉 Docker Compose 在删除容器的同时,也一并删除关联的数据卷,这将导致您的数据永久丢失!
3. 可以不中断服务,动态热更新吗?
答案:不可以对单个节点热更新,但集群可以实现服务的“滚动更新”。
- 单个节点: Docker Compose 机制决定了应用新配置必须经过“先销毁,再重建”的过程。因此,被更新的单个节点会有短暂的服务中断。
- 集群的优势: 这正是集群高可用性的体现!您可以执行 滚动更新 (Rolling Update):逐个更新集群中的节点。例如,先更新节点A,等待其恢复并重新加入集群后,再更新节点B,以此类推。在整个过程中,由于总有其他节点在正常工作,您的整体 MQTT 服务可以保持在线,对客户端的影响降到最低。
六、实战测试:验证集群消息路由
集群搭好了,它真的在协同工作吗?一个简单的“发布/订阅”测试就能证明一切。
- 准备工具:下载跨平台的 MQTT 客户端工具 MQTTX。
- 创建客户端A:使用 MQTTX 连接到 服务器 A (
192.168.0.240:1883),并订阅主题iot/cluster/test。 - 创建客户端B:使用 MQTTX 的新窗口,连接到 服务器 B (
192.168.0.188:1883)。 - 发布消息:在客户端 B 中,向主题
iot/cluster/test发布一条消息,例如Hello, High-Availability EMQX Cluster!。 - 见证奇迹:观察客户端 A 的窗口,它应该能立即收到这条消息。
这个测试完美地证明了:消息从一个节点进入,通过集群内部高效路由,成功分发给了连接在另一个节点上的客户端。您的集群正在完美地协同工作。
更多推荐



所有评论(0)