从零到三:手把手教你用Docker Compose滚动扩展EMQX 5.0集群(附扩容脚本)
从零到三:手把手教你用Docker Compose滚动扩展EMQX 5.0集群(附扩容脚本)
当业务流量突然激增时,一个原本稳定的双节点EMQX集群可能瞬间变得捉襟见肘。上周我就遇到了这样的场景:凌晨三点收到告警,两个节点CPU长期维持在90%以上,消息积压超过百万条。这时候,快速、安全地扩展集群规模就成了救命稻草。
本文将分享一套经过生产验证的扩容方案,重点解决三个核心问题:
- 如何在不中断服务的情况下动态添加新节点
- 滚动更新SEEDS列表的正确顺序与时机
- 扩容后的数据一致性与负载均衡验证
1. 扩容前的关键检查
在开始扩容操作前,必须确保现有集群处于健康状态。这就像给行驶中的汽车更换轮胎,必须先确认车辆还能保持平衡。
集群健康检查命令:
# 检查集群节点状态
docker exec emqx-node emqx ctl cluster status
# 查看节点负载情况
docker exec emqx-node emqx ctl status
关键指标阈值参考:
| 指标 | 安全阈值 | 危险阈值 | 检查方法 |
|---|---|---|---|
| CPU使用率 | <70% | ≥90% | top -p $(pgrep beam) |
| 内存使用 | <75% | ≥90% | free -m |
| 消息堆积数 | <10万 | ≥50万 | Dashboard监控 |
| 节点间延迟 | <10ms | ≥50ms | ping 其他节点IP |
如果发现以下情况,建议先解决问题再扩容:
- 任一节点状态为
unreachable - 节点间延迟超过20ms
- Mnesia数据库同步进度落后超过5分钟
2. 扩容操作全流程
2.1 准备新节点环境
新节点需要与现有集群完全一致的环境配置。这个脚本可以自动完成环境检查:
#!/bin/bash
# 新节点环境检查脚本 check_env.sh
# 检查Docker版本
DOCKER_VERSION=$(docker --version | awk '{print $3}' | tr -d ',')
if [[ "$DOCKER_VERSION" < "20.10" ]]; then
echo "ERROR: Docker版本过低,需要20.10以上"
exit 1
fi
# 检查Docker Compose版本
COMPOSE_VERSION=$(docker-compose --version | awk '{print $3}' | tr -d ',')
if [[ "$COMPOSE_VERSION" < "1.29" ]]; then
echo "ERROR: Docker Compose版本过低,需要1.29以上"
exit 1
fi
# 检查防火墙端口
PORTS=(4370 5370 1883 8883 18083)
for port in "${PORTS[@]}"; do
if ! sudo iptables -L -n | grep -q ":${port}"; then
echo "WARNING: 端口 $port 未开放,请检查防火墙规则"
fi
done
echo "环境检查通过"
2.2 动态更新SEEDS列表
这是整个扩容过程中最关键的步骤。错误的更新顺序可能导致集群分裂。正确的滚动更新流程应该是:
-
首先更新所有现有节点的SEEDS列表
在原有列表末尾追加新节点信息,例如:environment: - EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.1.100,emqx@192.168.1.101,emqx@192.168.1.102改为:
environment: - EMQX_CLUSTER__STATIC__SEEDS=emqx@192.168.1.100,emqx@192.168.1.101,emqx@192.168.1.102,emqx@192.168.1.103 -
按以下顺序滚动重启节点:
- 先重启负载最低的节点
- 每次间隔至少2分钟
- 使用健康检查确认节点已恢复
-
最后启动新节点
新节点的SEEDS列表必须包含自身地址
2.3 自动化扩容脚本
以下脚本可以自动完成从环境检查到加入集群的全过程:
#!/bin/bash
# 集群扩容脚本 scale_emqx.sh
# 配置区
NEW_NODE_IP="192.168.1.103" # 新节点IP
EXISTING_NODES=("192.168.1.100" "192.168.1.101") # 现有节点IP列表
COOKIE="YourStrongSecretCookie"
EMQX_VERSION="5.7.2"
# 生成新SEEDS列表
SEEDS_LIST=""
for node in "${EXISTING_NODES[@]}"; do
SEEDS_LIST+="emqx@${node},"
done
SEEDS_LIST+="emqx@${NEW_NODE_IP}"
# 创建docker-compose.yml
cat > docker-compose.yml <<EOF
version: '3.8'
services:
emqx-node:
image: emqx/emqx:${EMQX_VERSION}
container_name: emqx
restart: always
network_mode: "host"
environment:
- EMQX_NODE__NAME=emqx@${NEW_NODE_IP}
- EMQX_NODE__COOKIE=${COOKIE}
- EMQX_CLUSTER__DISCOVERY_STRATEGY=static
- EMQX_CLUSTER__STATIC__SEEDS=${SEEDS_LIST}
volumes:
- ./data:/opt/emqx/data
- ./log:/opt/emqx/log
EOF
# 准备目录
mkdir -p data log && chown -R 1000:1000 data log
# 启动服务
docker-compose up -d
echo "新节点${NEW_NODE_IP}已启动,等待加入集群..."
sleep 30
# 验证集群状态
if docker exec emqx emqx ctl cluster status | grep -q "${NEW_NODE_IP}"; then
echo "√ 节点已成功加入集群"
else
echo "× 节点加入集群失败,请检查日志"
docker-compose logs -t --tail=50
exit 1
fi
3. 扩容后验证
3.1 数据一致性检查
# 检查Mnesia表同步状态
docker exec emqx-node emqx eval 'mnesia:system_info(tables).'
# 对比各节点主题树
docker exec emqx-node emqx eval 'emqx_router:print().' | grep -c "topic:"
3.2 负载均衡测试
使用emqx_bench工具模拟客户端流量:
# 在新节点上启动发布者
./emqx_bench pub -h ${NEW_NODE_IP} -t load_test -c 100 -I 10
# 在旧节点上启动订阅者
./emqx_bench sub -h ${EXISTING_NODES[0]} -t load_test -c 100
观察指标变化:
| 节点IP | 连接数 | 消息速率(msg/s) | CPU使用率 |
|---|---|---|---|
| 192.168.1.100 | 3,250 | 12,000 | 62% |
| 192.168.1.101 | 3,180 | 11,800 | 58% |
| 192.168.1.103 | 3,570 | 13,200 | 65% |
理想情况下,各节点指标应该趋于均衡,差异不超过15%。
4. 常见问题排错指南
4.1 新节点无法加入集群
现象:
新节点日志中出现[error] Mnesia(emqx@new_node): ** Node 'emqx@existing_node' not responding **
解决方案:
- 检查所有节点的cookie是否一致
docker exec emqx-node cat /opt/emqx/etc/emqx.conf | grep node.cookie - 验证网络连通性
docker run --rm --net=host appropriate/curl curl -v telnet://existing_node:4370 - 检查防火墙规则
sudo iptables -L -n | grep 5370
4.2 集群出现脑裂
现象:cluster status显示部分节点为unreachable,但实际网络正常
恢复步骤:
- 停止所有节点
docker-compose down - 选择数据最新的节点作为主节点
- 其他节点清空data/mnesia目录后重新启动
4.3 负载不均衡
调整策略:
# 启用负载均衡插件
docker exec emqx-node emqx_ctl plugins load emqx_lb
# 设置节点权重
docker exec emqx-node emqx_ctl lb node weight emqx@new_node 80
5. 进阶:从三节点到N节点
当集群规模超过5个节点时,建议考虑以下优化:
-
网络拓扑:
使用专线或VPC对等连接降低节点间延迟 -
发现策略:
将static改为dns或etcd实现动态发现 -
分区容忍:
配置emqx.conf中的cluster.core_nodes参数:cluster.core_nodes = emqx@node1,emqx@node2,emqx@node3 -
监控告警:
使用Prometheus监控关键指标:# prometheus.yml 配置示例 scrape_configs: - job_name: 'emqx' static_configs: - targets: ['node1:18083','node2:18083','node3:18083'] metrics_path: '/api/v5/prometheus/stats'
扩容完成后,记得更新负载均衡器配置,将新节点加入后端服务器组。在AWS ALB或Nginx中,可以使用API动态更新:
# AWS ALB示例
aws elbv2 register-targets \
--target-group-arn your-target-group-arn \
--targets Id=${NEW_NODE_IP},Port=1883
更多推荐
所有评论(0)