1. 为什么需要EMQX集群?

第一次接触EMQX时,我像大多数开发者一样从单节点部署开始。但当项目上线后,很快就遇到了连接数暴增导致的性能瓶颈。某个凌晨三点,服务器突然崩溃导致数万设备掉线,那次惨痛经历让我深刻认识到:物联网项目从原型到生产,集群部署不是可选项而是必选项

EMQX作为开源MQTT消息服务器,单节点理论上能支持百万级连接。但在实际生产环境中,单节点部署存在三个致命缺陷:首先是单点故障风险,一旦服务器宕机整个系统就会瘫痪;其次是性能天花板,单个服务器的CPU、内存和网络带宽终归有限;最后是扩展不灵活,无法根据业务增长动态扩容。这些问题在我负责的智慧园区项目中尤为明显——当接入设备从1千台突然增加到5万台时,单节点架构根本招架不住。

集群化部署的核心价值在于高可用水平扩展。通过多节点协同工作,不仅能实现故障自动转移(比如某个节点宕机时流量会自动迁移到健康节点),还能通过增加节点来线性提升系统吞吐量。去年我们为某车企搭建的车联网平台就采用了5节点EMQX集群,成功应对了"双十一"期间300万+车辆的并发连接。

2. 单节点部署:从零开始的正确姿势

2.1 环境准备与依赖检查

虽然EMQX号称"开箱即用",但生产环境部署绝不能真的直接运行完事。我建议先执行以下检查清单:

  1. 操作系统优化:关闭swap分区(sudo swapoff -a)能显著提升Erlang虚拟机性能,修改系统最大文件打开数(ulimit -n 1000000)避免连接数达到上限。在CentOS上还需要特别检查OpenSSL版本:

    openssl version
    # 必须 >= 1.1.1 否则会出现TLS握手失败
    
  2. 端口规划:EMQX默认使用6个关键端口,如果与其他服务冲突会导致启动失败。用这个命令快速检查:

    netstat -tulnp | grep -E '1883|8883|8083|18083'
    

    建议生产环境改用自定义端口(比如11883替代1883),能有效避免端口扫描攻击。

  3. 资源评估:根据预期连接数配置合适的服务器规格。我的经验值是:

    • 1万连接:2核4G
    • 10万连接:4核8G
    • 100万连接:8核16G+SSD存储

2.2 三种安装方式对比

EMQX支持多种安装方式,各有利弊:

方式 适用场景 优点 缺点
二进制包 快速测试环境 无需依赖,解压即用 升级麻烦
Docker 开发/演示环境 环境隔离,快速部署 网络性能损失约5%
Kubernetes 云原生生产环境 自动扩缩容,高可用 运维复杂度高

对于新手,我推荐先用Docker体验完整功能:

docker run -d --name emqx \
  -p 1883:1883 -p 8081:8081 \
  -p 8083:8083 -p 18083:18083 \
  -v /etc/localtime:/etc/localtime \
  emqx/emqx:5.0.0

这个命令除了映射必要端口,还挂载了时区文件避免日志时间错乱——这是很多教程没提到但实际很重要的细节。

3. 集群部署实战:从Docker到K8s

3.1 基于Docker的集群搭建

在开发环境搭建集群,docker-compose是最佳选择。这是我的标准配置模板:

version: '3'
services:
  emqx1:
    image: emqx:5.0.0
    environment:
      - EMQX_NODE_NAME=emqx@node1
      - EMQX_CLUSTER__DISCOVERY_STRATEGY=static
      - EMQX_CLUSTER__STATIC__SEEDS=emqx@node1,emqx@node2
    networks:
      emqx_net:
        aliases: [node1]

  emqx2:
    image: emqx:5.0.0 
    environment:
      - EMQX_NODE_NAME=emqx@node2
      - EMQX_CLUSTER__DISCOVERY_STRATEGY=static
      - EMQX_CLUSTER__STATIC__SEEDS=emqx@node1,emqx@node2
    networks:
      emqx_net:
        aliases: [node2]

networks:
  emqx_net:
    driver: bridge

启动后执行docker exec -it emqx1 emqx ctl cluster status应该能看到两个节点组成集群。这里有个坑要注意:节点名称必须带@符号,否则集群组建会失败。

3.2 Kubernetes生产级部署

对于正式环境,EMQX Operator极大简化了K8s部署流程。以下是核心配置示例:

apiVersion: apps.emqx.io/v1beta1
kind: EmqxEnterprise
metadata:
  name: emqx-ee
spec:
  replicas: 3
  template:
    spec:
      emqxContainer:
        image: emqx/emqx-ee:5.0.0
        resources:
          requests:
            cpu: "2"
            memory: "4Gi"
  serviceTemplate:
    spec:
      type: LoadBalancer
      ports:
        - name: mqtt
          port: 1883
          targetPort: 1883

这个配置会创建:

  1. 3个Pod组成的EMQX集群
  2. 每个Pod分配2核4G资源
  3. 通过LoadBalancer暴露MQTT服务

我曾用这个方案在AWS上部署,配合自动伸缩策略(HPA),成功处理了世界杯期间某体育APP的千万级推送消息。

4. 集群优化:性能提升50%的实战技巧

4.1 网络拓扑优化

EMQX集群节点间通信频繁,错误的网络配置会导致性能急剧下降。经过多次压测验证,这些配置效果显著:

  1. 禁用TCP_NODELAY(修改emqx.conf):

    cluster.tcp_nodelay = false
    

    虽然会增加少量延迟,但能减少小包传输次数,集群吞吐量提升约20%。

  2. 启用TCP快速打开

    sysctl -w net.ipv4.tcp_fastopen=3
    

    特别适合跨可用区部署的场景,连接建立时间缩短40%。

4.2 持久化配置

消息持久化是保证业务连续性的关键。EMQX支持多种后端,我的选型建议是:

  • Redis:适合消息量小但读写频繁的场景
  • MySQL:需要事务支持的场景
  • PostgreSQL:消息量大且需要复杂查询
  • TimescaleDB:物联网时序数据场景

配置PostgreSQL持久化的示例:

# emqx.conf
persistence.postgresql.pool_size = 8
persistence.postgresql.server = "10.0.0.1:5432"
persistence.postgresql.username = "emqx"
persistence.postgresql.password = "secret"
persistence.postgresql.database = "mqtt_msg"

4.3 监控与调优

没有监控的集群就像盲人骑马。我习惯用Prometheus+Grafana搭建监控体系,关键指标包括:

  • 连接增长率:突然飙升可能意味着设备异常
  • 消息吞吐量:判断是否需要扩容
  • 集群RPC延迟:超过50ms说明网络有问题

EMQX内置了Prometheus支持,只需在配置中开启:

prometheus.enable = true
prometheus.interval = 15s

在Grafana中导入官方仪表板(ID: 17446),就能看到这样的监控视图。去年我们就是通过监控发现某个AZ的网络延迟异常,及时切换流量避免了事故。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐