Skip to content

从 Mosquitto 迁移到 EMQX

本页介绍了如何将现有的 Eclipse Mosquitto 部署迁移到 EMQX。本指南适用于计划从轻量级单节点 MQTT Broker 升级至可扩展的分布式 MQTT 平台的系统管理员。迁移过程利用了 EMQX 对标准 MQTT 协议的兼容性,并提供了一个清晰的路径,用于迁移配置、安全认证信息和集成逻辑。

迁移概览

迁移过程分为三个主要阶段:

  1. 盘点 Mosquitto 资源:收集配置文件(mosquitto.conf)、安全文件(密码文件、ACL、证书),并了解当前数据流。
  2. 配置 EMQX:将 Mosquitto 设置转换为 EMQX 的配置文件(emqx.conf,HOCON 格式),导入用户凭据,并使用规则引擎重建访问控制和数据集成逻辑。
  3. 更新设备与集成:将设备连接重定向至 EMQX 集群(通常无需修改端口配置),并验证系统运行是否正常。
参数 / 文件资源Mosquitto 示例EMQX 示例说明
主配置文件/etc/mosquitto/mosquitto.conf/etc/emqx/emqx.confEMQX 使用分层的 HOCON 配置格式。
网络端口1883 (TCP), 8883 (SSL)1883 (TCP), 8883 (SSL)标准端口一致,通常无需修改设备配置。
用户凭据/etc/mosquitto/passwd内置数据库(Mnesia)可通过 API 导入现有密码哈希值。
访问控制/etc/mosquitto/acl_file/etc/emqx/acl.conf可直接映射允许/拒绝规则。
桥接(Bridges)connection bridge_name数据连接器与规则(Data Connectors & Rules)使用动态数据路由替代静态桥接。
持久化mosquitto.dbdata/(Mnesia + RocksDB)EMQX 自动处理会话持久化。

阶段一:盘点 Mosquitto 资源

收集配置与证书文件

首先确定关键配置文件的位置,通常在 mosquitto.conf 中定义:

  • 主配置文件: 通过 include_dir 引用,或默认位于 /etc/mosquitto/mosquitto.conf
  • 证书文件: 查找 certfilekeyfilecafile 的路径。
  • 安全文件: 查找 password_fileacl_file

将证书文件(server.crtserver.keyca.crt)复制到 EMQX 节点,一般放置于 /etc/emqx/certs/

分析认证与授权机制

确定当前的认证方式:

  • 密码文件: 最常见方式。可迁移到 EMQX 内部数据库。
  • 插件(mosquitto-auth-plug): 若使用 SQL 或 LDAP,需在 EMQX 中配置相应的认证后端。

阶段二:配置 EMQX,使其与 Mosquitto 保持一致

重建 MQTT 监听器

Mosquitto 按顺序定义监听器,而 EMQX 按类型(TCP、SSL、WebSocket)在 emqx.conf 中分组定义。

Mosquitto (mosquitto.conf) 示例:

properties
# 默认监听器
port 1883
max_connections -1

# SSL 监听器
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

EMQX (emqx.conf) 示例:

hocon
listeners.tcp.default {
  bind = "0.0.0.0:1883"
  max_connections = infinity
}

listeners.ssl.default {
  bind = "0.0.0.0:8883"
  ssl_options {
    certfile = "/etc/emqx/certs/server.crt"
    keyfile  = "/etc/emqx/certs/server.key"
  }
}

映射 MQTT 协议参数

将核心协议配置项进行对应转换,以保持客户端行为一致。

Mosquitto 指令EMQX HOCON 参数说明
max_queued_messagesmqtt.max_mqueue_len每个客户端的离线消息最大缓冲数量。
persistent_client_expirationmqtt.session_expiry_interval断开连接后会话状态的保留时长。
message_size_limitmqtt.max_packet_sizeMQTT 报文的最大允许大小。
log_dest filelog.file.enable = true启用日志文件输出。

注意: Mosquitto 仅支持全局会话过期时间,而 EMQX(MQTT 5.0)支持按客户端自定义会话过期时间。 对于旧版 MQTT 3.1.1 客户端,可在 EMQX 中设置全局默认值以保持一致。

迁移认证

EMQX 支持多种认证后端。在大多数从 Mosquitto 迁移的场景中,主要目标是保留现有用户认证信息,避免用户重置密码。

方案 1:重新创建用户(批量导入)

如果您能够获取原始的明文密码,可以通过 EMQX HTTP API 批量导入。

批量导入 CSV 格式示例:

创建一个名为 users.csv 的文件,并包含以下列:

csv
user_id,password,is_superuser
device001,secret123,false
admin,adminPass,true

导入命令:

使用 curl 命令上传该文件。参数 type=plain 表示 EMQX 在导入过程中会自动对密码进行哈希处理。

bash
curl -v -u admin:public -X POST \
  -H "Content-Type: multipart/form-data" \
  -F "filename=@users.csv" \
  "http://localhost:18083/api/v5/authentication/password_based:built_in_database/import_users?type=plain"
  • admin:public 替换为你的 EMQX Dashboard 用户名与密码。
  • 确认认证器 (password_based:built_in_database) 已存在并与您的配置匹配。

方案 2:导入 Mosquitto 密码文件(高级)

如果您拥有大量用户,并且仅持有 mosquitto.passwd 文件(其中包含已哈希的密码),可以通过 Erlang 脚本将这些用户数据直接导入到 EMQX 的内置数据库中。

步骤 1:配置认证机制

在导入数据之前,需要在 EMQX 中配置基于密码的认证,并使用内置数据库后端。必须按照以下设置,以确保与 Mosquitto 默认的密码哈希算法保持一致:

  • 算法 (Algorithm): pbkdf2
  • MAC 函数 (MAC Function): sha512
  • 迭代次数 (Iterations): 101
  • 密钥长度 (DK Length): 32

注意: 上述参数(101 次迭代,sha512)与 Mosquitto 默认配置完全一致。尽管这些参数与 EMQX 的默认安全配置(通常更为严格)不同,但在迁移时必须保持相同设置,以便验证原有密码哈希的有效性。

步骤 2:复制密码文件

mosquitto.passwd 文件复制到 EMQX 节点(例如 /tmp/mosquitto.passwd),并确保 emqx 系统用户对该文件具有读取权限。

步骤 3:执行导入脚本

在 EMQX 节点上运行以下命令。该脚本会读取 mosquitto.passwd 文件内容,解析并解码 Base64 格式的盐值(Salt)和哈希值(Hash),然后将用户记录直接写入数据库。

bash
emqx eval "
File = \"/tmp/mosquitto.passwd\",
{ok, Bin} = file:read_file(File),
Lines = binary:split(Bin, <<\"\n\">>, [global, trim]),
lists:foreach(fun(Line) ->
    case binary:split(Line, <<\":\">>) of
        [Username, <<\"\$7$\", Rest/binary>>] ->
            [_, SaltB64, HashB64] = binary:split(Rest, <<\"$\">>, [global]),
            Salt = base64:decode(SaltB64),
            Hash = binary:part(emqx_utils:bin_to_hexstr(base64:decode(HashB64), lower), 0, 64),
            Record = {user_info, {'mqtt:global', Username}, Hash, Salt, false},
            mnesia:dirty_write(emqx_authn_mnesia, Record);
        _ -> ok
    end
end, Lines)."
可选方案:外部数据库

对于需要与现有用户管理系统集成的企业级部署,您也可以选择将用户数据迁移至外部 SQL 数据库(如 MySQL 或 PostgreSQL)。 EMQX 支持动态 SQL 查询,可灵活适配不同的数据库架构与字段格式,从而无缝集成至企业现有的身份验证体系。

方案 3:双向 TLS 认证(mTLS)

如果您的 Mosquitto 部署使用 X.509 客户端证书(Mutual TLS)进行身份认证,那么在迁移至 EMQX 时,需要在 EMQX 的监听器中启用并配置客户端证书验证。

Mosquitto 配置示例:

properties
require_certificate true
use_identity_as_username true
cafile /etc/mosquitto/ca.crt

EMQX 配置示例:

hocon
listeners.ssl.default {
  bind = "0.0.0.0:8883"
  ssl_options {
    cacertfile = "/etc/emqx/certs/ca.crt"
    verify = verify_peer
    fail_if_no_peer_cert = true
  }
}
  • 请确保将同一 CA 证书(ca.crt)复制到 EMQX 节点。
  • 若启用 use_identity_as_username,EMQX 将默认使用证书的 CN(Common Name)作为用户名。

迁移授权(ACL)

完成认证配置后,迁移主题级访问控制规则。

Mosquitto 的 ACL 语法与 EMQX 的 acl.conf 非常相似。

Mosquitto (acl_file) 示例:

properties
user Alice
topic read sensors/#
pattern write devices/%u/data

EMQX (acl.conf) 示例:

erlang
{allow, {user, "Alice"}, subscribe, ["sensors/#"]}.
{allow, all, publish, ["devices/${username}/data"]}.
  • %u 替换为 ${username}(或 ${clientid})。
  • read 映射为 subscribewrite 映射为 publish

配置数据集成(替换 Bridges 与脚本)

Mosquitto 使用桥接功能实现消息转发,并使用外部脚本(Python/Node.js)进行数据处理。在 EMQX 中,这些功能可由内置的规则引擎数据集成替代。

EMQX 规则引擎允许您在消息转发至外部系统之前,对消息进行筛选、过滤与转换,并通过连接器将结果输出到目标系统。

场景 1:转发数据到另一 MQTT Broker

代替 Mosquitto 中的 connection bridge_name 配置:

  1. 在 EMQX Dashboard 中创建 MQTT Broker 连接器

  2. 创建一条规则

    sql
    SELECT * FROM "#"

    并将结果转发至该连接器。

场景 2:替换 Python 处理脚本

假设您原本使用一个 Python 脚本,订阅 sensors/+/temp 主题,筛选出温度值大于 30 的数据,并将其写入数据库。

在 EMQX 中,可以通过规则引擎实现同样的逻辑,而无需外部脚本:

  1. 删除脚本。

  2. 创建规则:

    sql
    SELECT payload.temp as temperature, topic, timestamp
    FROM "sensors/+/temp"
    WHERE temperature > 30
  3. 添加动作:配置一个数据集成,例如连接 InfluxDB 或 HTTP 服务,将筛选后的数据直接写入目标系统。

阶段三:更新设备与集成

更新客户端连接

由于 EMQX 使用标准 MQTT 端口(1883 / 8883),如果您的设备是通过 DNS 域名进行连接的,通常无需修改设备配置。

您只需更新 DNS 记录,将域名(例如 mqtt.yourdomain.com)指向 EMQX 集群的负载均衡器(Load Balancer)或集群节点的 IP 地址。

验证连接状态

通过 EMQX Dashboard 监控设备连接状态,确保客户端能够成功接入。

  • 查看连接数是否随设备上线而增加。

    您也可以使用命令行工具验证连接状态:

    bash
    emqx_ctl clients list

    或在 Dashboard 中通过菜单监控 -> 客户端查看连接详情。

  • 检查日志是否存在认证错误(例如密码哈希算法不匹配或缺少证书等问题)。

高级迁移方案

本节适用于希望实现不中断服务迁移的场景。

桥接过渡策略(Zero Downtime)

若希望在迁移过程中不中断服务,可按以下步骤进行:

  1. 并行部署 EMQX 与 Mosquitto。

    在现有 Mosquitto 实例旁部署 EMQX 节点,确保两者可正常通信。

  2. 配置 Mosquitto 桥接至 EMQX:

    在 Mosquitto 中设置桥接,将所有消息转发至 EMQX。在 mosquitto.conf 中添加以下配置:

    properties
    # mosquitto.conf
    connection migrate_uplink
    address emqx-server:1883
    topic # out 0
    topic # in 0
  3. 迁移消费者:

    将后端应用程序或数据消费者的连接端点切换至 EMQX。 此时它们将同时接收来自 EMQX 连接设备与仍连接到 Mosquitto 的设备的数据。

  4. 逐步迁移设备:

    将终端设备逐步从 Mosquitto 的连接地址切换至 EMQX 的新接入点。

  5. 下线 Mosquitto:

    当确认 Mosquitto 已无活跃连接后,移除桥接配置并关闭 Mosquitto 服务。

验证清单

在切换生产环境流量之前,请确保以下项目均已验证通过:

  • 监听器: TCP(1883)与 SSL(8883)端口已开放并可正常接受连接。
  • 认证: 用户可使用原密码正常登录。
  • ACL: 用户仅能访问授权主题。
  • 数据流: 设备发布的消息能被订阅端或后端应用正常接收。
  • 持久化: Broker 重启后保留消息可正常恢复(确保 retain_available = true)。

总结

从 Mosquitto 迁移至 EMQX,可在保持协议兼容的同时显著提升系统的可扩展性与可靠性。通过映射原有配置,并利用 EMQX 的规则引擎替代外部脚本与桥接机制,可有效简化系统架构,为大规模 MQTT 部署做好准备。