外观
Apusic ADMQ MQTT 迁移手册
版本: 1.0 适用场景: 从 EMQX、HiveMQ、Mosquitto 等迁移至 Apusic ADMQ MQTT 更新日期: 2026-06
目录
1. 迁移前准备
1.1 迁移前信息收集
在开始迁移前,请收集现有系统的以下信息:
连接信息:
- [ ] 当前 Broker 地址和端口
- [ ] 在线客户端峰值数量
- [ ] 每秒消息吞吐量(TPS)
- [ ] 使用的 MQTT 协议版本(3.1/3.1.1/5.0)
- [ ] 是否使用 TLS/SSL,证书类型
功能使用情况:
- [ ] 使用的认证方式(用户名密码/证书/匿名)
- [ ] 是否使用 ACL 授权
- [ ] 是否有保留消息(数量、大小)
- [ ] 是否使用持久会话
- [ ] 是否使用共享订阅
- [ ] 是否有消息桥接或外部集成
- [ ] 主题命名规范
数据:
- [ ] 需迁移的用户账号列表
- [ ] 现有保留消息
1.2 迁移策略选择
| 策略 | 适用场景 | 风险 |
|---|---|---|
| 直接切换 | 系统可接受短暂停机;客户端少;测试环境 | 停机窗口 |
| 灰度迁移 | 生产环境;客户端多;需要回滚能力 | 双系统并存周期较长 |
| 并行双写 | 不允许停机;关键业务 | 资源成本高 |
推荐方案:灰度迁移
阶段一(准备):搭建 ADMQ,导入用户数据,验证功能
↓
阶段二(灰度):将 10-20% 客户端切换到 ADMQ,观察稳定性
↓
阶段三(扩大):逐批扩大迁移比例(20% → 50% → 100%)
↓
阶段四(下线):下线旧 Broker2. 与主流 MQTT Broker 功能对照
2.1 功能支持对照表
| 功能 | Apusic ADMQ | EMQX 5.x | HiveMQ 4.x | Mosquitto 2.x |
|---|---|---|---|---|
| MQTT 3.1 | ✅ | ✅ | ✅ | ✅ |
| MQTT 3.1.1 | ✅ | ✅ | ✅ | ✅ |
| MQTT 5.0 | ✅ | ✅ | ✅ | ✅ |
| QoS 0/1/2 | ✅ | ✅ | ✅ | ✅ |
| 保留消息 | ✅ | ✅ | ✅ | ✅ |
| 遗嘱消息 | ✅ | ✅ | ✅ | ✅ |
| 通配符订阅 | ✅ | ✅ | ✅ | ✅ |
| 共享订阅 | ✅ | ✅ | ✅ | ✅(2.0+) |
| 持久会话 | ✅ | ✅ | ✅ | ✅ |
| WebSocket | ✅ | ✅ | ✅ | ✅ |
| TLS/mTLS | ✅ | ✅ | ✅ | ✅ |
| 内置数据库认证 | ✅ | ✅ | ✅ | ✅ |
| HTTP 认证 | ✅ | ✅ | ✅(插件) | ✅(插件) |
| JWT 认证 | ✅ | ✅ | ✅(插件) | ❌ |
| LDAP 认证 | ✅ | ✅ | ✅(企业版) | ❌ |
| 数据库认证(MySQL 等) | ✅ | ✅ | ✅(企业版) | ❌ |
| 集群 | ✅ | ✅ | ✅ | ❌(需桥接) |
| 规则引擎 | ✅ | ✅ | ✅(企业版) | ❌ |
| REST API | ✅ | ✅ | ✅ | ❌ |
| Web 控制台 | ✅ | ✅ | ✅ | ❌ |
| Prometheus 监控 | ✅ | ✅ | ✅ | ✅(插件) |
| QUIC | ✅ | ✅ | ❌ | ❌ |
| CoAP 网关 | ✅ | ✅ | ❌ | ❌ |
| MQTT-SN 网关 | ✅ | ✅ | ❌ | ❌ |
2.2 配置文件格式对照
| Broker | 配置格式 | 主配置文件 |
|---|---|---|
| Apusic ADMQ | HOCON | config/mqtt.conf |
| EMQX 5.x | HOCON | etc/emqx.conf |
| EMQX 4.x | 自定义格式 | etc/emqx.conf |
| HiveMQ | XML | config/config.xml |
| Mosquitto | INI 风格 | mosquitto.conf |
3. 从 EMQX 迁移
3.1 迁移说明
ADMQ MQTT 使用 HOCON 格式配置文件,与 EMQX 5.x 格式高度兼容:
- 从 EMQX 5.x 迁移: 配置格式基本一致,迁移成本极低
- 从 EMQX 4.x 迁移: 配置格式有变化,需要更新
3.2 EMQX 5.x → ADMQ(配置几乎完全兼容)
EMQX 5.x 的配置文件(HOCON 格式)可以直接或少量修改后用于 ADMQ。
主要差异:
| 项目 | EMQX 5.x | Apusic ADMQ |
|---|---|---|
| 主配置文件路径 | etc/emqx.conf | config/mqtt.conf |
| 启动命令 | emqx start | ./bin/admq-daemon start mqtt server |
| 控制台命令 | emqx_ctl | ./bin/admq mqtt admin |
迁移步骤:
- 复制 EMQX 5.x 的配置内容到
config/mqtt.conf - 调整启动命令
- 验证运行
bash
# EMQX 5.x 导出用户数据
# 通过 EMQX REST API 导出
curl -u admin:public http://emqx-host:18083/api/v5/authentication/password_based:built_in_database/users \
> users_backup.json
# 导入到 ADMQ
curl -u admin:public -X POST \
http://admq-host:18083/api/v5/authentication/password_based:built_in_database/import_users \
-H "Content-Type: application/json" \
-d @users_backup.json3.3 EMQX 4.x → ADMQ(需配置适配)
EMQX 4.x 使用旧版配置格式,需要转换为 HOCON 格式。
EMQX 4.x 认证配置对照:
bash
# EMQX 4.x 格式(auth.conf 或 emqx.conf)
auth.http.auth_req = http://auth.example.com/mqtt/auth
auth.http.auth_req.method = post
auth.http.auth_req.params = username=%u,password=%P,clientid=%cini
## ADMQ / EMQX 5.x HOCON 格式
authentication = [
{
mechanism = password_based
backend = http
url = "http://auth.example.com/mqtt/mqtt/auth"
method = post
body {
username = "${username}"
password = "${password}"
clientid = "${clientid}"
}
}
]EMQX 4.x ACL 对照:
bash
# EMQX 4.x 格式
acl.http.acl_req = http://auth.example.com/mqtt/acl
acl.http.acl_req.method = get
acl.http.acl_req.params = username=%u,clientid=%c,access=%A,topic=%tini
## ADMQ / EMQX 5.x HOCON 格式
authorization {
sources = [
{
type = http
enable = true
url = "http://auth.example.com/mqtt/acl"
method = get
headers {}
body {
username = "${username}"
clientid = "${clientid}"
action = "${action}"
topic = "${topic}"
}
}
]
}EMQX 4.x 监听器配置对照:
bash
# EMQX 4.x
listener.tcp.external = 0.0.0.0:1883
listener.tcp.external.max_connections = 1024000
listener.ssl.external = 0.0.0.0:8883
listener.ssl.external.keyfile = etc/certs/key.pem
listener.ssl.external.certfile = etc/certs/cert.pem
listener.ssl.external.cacertfile = etc/certs/cacert.pemini
## ADMQ / EMQX 5.x HOCON 格式
listeners.tcp.default {
bind = "0.0.0.0:1883"
max_connections = 1024000
}
listeners.ssl.default {
bind = "0.0.0.0:8883"
ssl_options {
keyfile = "${ADMQ_ETC_DIR}/certs/key.pem"
certfile = "${ADMQ_ETC_DIR}/certs/cert.pem"
cacertfile = "${ADMQ_ETC_DIR}/certs/cacert.pem"
}
}EMQX 4.x 内置 ACL 文件(etc/acl.conf):
EMQX 4.x 的 acl.conf 格式与 ADMQ 完全兼容,可以直接使用。
4. 从 HiveMQ 迁移
4.1 配置对照
HiveMQ 监听器配置 → ADMQ:
xml
<!-- HiveMQ config.xml -->
<listeners>
<tcp-listener>
<port>1883</port>
<bind-address>0.0.0.0</bind-address>
</tcp-listener>
<tls-tcp-listener>
<port>8883</port>
<bind-address>0.0.0.0</bind-address>
<tls>
<keystore>
<path>/path/to/keystore.jks</path>
<password>changeit</password>
<private-key-password>changeit</private-key-password>
</keystore>
</tls>
</tls-tcp-listener>
<websocket-listener>
<port>8083</port>
<bind-address>0.0.0.0</bind-address>
</websocket-listener>
</listeners>ini
## ADMQ 等价配置
listeners.tcp.default {
bind = "0.0.0.0:1883"
}
listeners.ssl.default {
bind = "0.0.0.0:8883"
ssl_options {
# 注意:ADMQ 使用 PEM 格式,需先转换 JKS
keyfile = "/path/to/key.pem"
certfile = "/path/to/cert.pem"
cacertfile = "/path/to/cacert.pem"
}
}
listeners.ws.default {
bind = "0.0.0.0:8083"
}HiveMQ JKS 证书 → PEM 格式转换:
bash
# 步骤1:从 JKS 导出 P12
keytool -importkeystore \
-srckeystore keystore.jks \
-destkeystore keystore.p12 \
-deststoretype PKCS12 \
-deststorepass changeit \
-srcstorepass changeit
# 步骤2:从 P12 导出 PEM 证书
openssl pkcs12 -in keystore.p12 -nokeys -out cert.pem -passin pass:changeit
# 步骤3:从 P12 导出私钥
openssl pkcs12 -in keystore.p12 -nocerts -nodes -out key.pem -passin pass:changeit
# 步骤4:导出 CA 证书(如有 truststore)
keytool -exportcert -keystore truststore.jks -alias ca-cert \
-file cacert.der -storepass changeit
openssl x509 -inform DER -in cacert.der -out cacert.pem4.2 HiveMQ 认证插件迁移
HiveMQ 文件认证(file-auth)→ ADMQ 内置数据库:
HiveMQ 的 credentials.xml 格式:
xml
<mqtt-file-authenticator>
<credentials>
<credential>
<username>device001</username>
<password>secret123</password>
</credential>
</credentials>
</mqtt-file-authenticator>迁移脚本(Python):
python
import xml.etree.ElementTree as ET
import requests
import json
ADMQ_URL = "http://localhost:18083"
ADMQ_AUTH = ("admin", "public")
def import_hivemq_users(credentials_xml_path):
tree = ET.parse(credentials_xml_path)
root = tree.getroot()
for cred in root.findall('.//credential'):
username = cred.find('username').text
password = cred.find('password').text
resp = requests.post(
f"{ADMQ_URL}/api/v5/authentication/password_based:built_in_database/users",
auth=ADMQ_AUTH,
json={"user_id": username, "password": password}
)
if resp.status_code == 201:
print(f"✅ 导入用户: {username}")
else:
print(f"❌ 失败: {username} - {resp.text}")
import_hivemq_users("credentials.xml")HiveMQ HTTP 认证插件 → ADMQ HTTP 认证:
ini
## ADMQ HTTP 认证(对接原有 HiveMQ HTTP 认证后端)
authentication = [
{
mechanism = password_based
backend = http
method = post
url = "http://your-auth-service/auth"
body {
username = "${username}"
password = "${password}"
client_id = "${clientid}"
}
headers {
"Content-Type" = "application/json"
}
}
]4.3 HiveMQ 权限扩展迁移
HiveMQ 使用 Java 插件实现权限控制(AuthorizerProvider),迁移到 ADMQ 有以下两个方案:
方案 A:使用 HTTP 授权(推荐)
将 HiveMQ 的授权逻辑封装为 HTTP 服务:
ini
authorization {
sources = [
{
type = http
enable = true
url = "http://your-authz-service/mqtt/acl"
method = post
body {
username = "${username}"
clientid = "${clientid}"
topic = "${topic}"
action = "${action}" # publish 或 subscribe
}
}
]
no_match = deny
}方案 B:使用内置数据库 ACL 规则
在管理控制台的"授权规则"中配置 ACL 规则,适合规则数量有限的场景。
5. 从 Mosquitto 迁移
5.1 配置对照
Mosquitto mosquitto.conf → ADMQ config/mqtt.conf:
| Mosquitto 配置 | ADMQ 等价配置 |
|---|---|
port 1883 | listeners.tcp.default { bind = "0.0.0.0:1883" } |
listener 8883 | listeners.ssl.default { bind = "0.0.0.0:8883" } |
cafile /path/ca.crt | ssl_options { cacertfile = "..." } |
certfile /path/cert.crt | ssl_options { certfile = "..." } |
keyfile /path/key.key | ssl_options { keyfile = "..." } |
max_connections 1000 | listeners.tcp.default { max_connections = 1000 } |
persistent_client_expiration 2h | mqtt { session_expiry_interval = 2h } |
message_size_limit 1048576 | mqtt { max_packet_size = 1MB } |
max_queued_messages 1000 | mqtt { max_mqueue_len = 1000 } |
allow_anonymous true | authorization { no_match = allow } |
allow_anonymous false | 配置认证后端 |
完整示例对照:
bash
# Mosquitto mosquitto.conf
port 1883
listener 8883
cafile /etc/mosquitto/ca.crt
certfile /etc/mosquitto/server.crt
keyfile /etc/mosquitto/server.key
require_certificate false
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl
max_connections 10000
message_size_limit 1048576
persistent_client_expiration 2h
max_queued_messages 1000
log_dest file /var/log/mosquitto/mosquitto.log
log_type allini
# ADMQ config/mqtt.conf 等价配置
listeners.tcp.default {
bind = "0.0.0.0:1883"
max_connections = 10000
}
listeners.ssl.default {
bind = "0.0.0.0:8883"
ssl_options {
cacertfile = "/etc/admq/ssl/ca.crt"
certfile = "/etc/admq/ssl/server.crt"
keyfile = "/etc/admq/ssl/server.key"
verify = verify_none
}
}
mqtt {
max_packet_size = 1MB
session_expiry_interval = 2h
max_mqueue_len = 1000
}
## 认证(替代 Mosquitto password_file)
authentication = [
{
mechanism = password_based
backend = built_in_database
user_id_type = username
}
]
## ACL(替代 Mosquitto acl_file,可使用内置数据库或文件 ACL)
authorization {
sources = [
{ type = built_in_database, enable = true }
]
no_match = deny
}
log {
file {
level = info
rotation_size = "100MB"
rotation_count = 10
}
}5.2 Mosquitto 密码文件迁移
Mosquitto 密码文件(/etc/mosquitto/passwd)格式为:
username:$7$...(加密后的密码哈希)由于哈希算法不同,无法直接导入,需要重置密码。
迁移方案:
- 导出用户名列表(不含密码)
- 通知用户使用临时密码首次登录
- 引导用户修改密码
bash
# 提取 Mosquitto 密码文件中的用户名列表
cut -d: -f1 /etc/mosquitto/passwd > usernames.txt
# 批量创建 ADMQ 用户(设置临时密码)
while IFS= read -r username; do
curl -s -u admin:public -X POST \
"http://localhost:18083/api/v5/authentication/password_based:built_in_database/users" \
-H "Content-Type: application/json" \
-d "{\"user_id\": \"${username}\", \"password\": \"TempPass123!\"}"
echo "创建用户: $username"
done < usernames.txt5.3 Mosquitto ACL 文件迁移
Mosquitto acl 文件格式:
# 所有用户的通用规则
topic read $SYS/#
# 用户级规则
user alice
topic readwrite devices/alice/#
user bob
topic read status/#
topic write commands/bobMosquitto ACL → ADMQ 内置数据库 ACL 对照:
| Mosquitto | ADMQ 动作 | 说明 |
|---|---|---|
read | subscribe | 订阅权限 |
write | publish | 发布权限 |
readwrite | all | 发布+订阅 |
deny | deny | 拒绝 |
批量导入 ACL 脚本:
python
import re
import requests
ADMQ_URL = "http://localhost:18083"
ADMQ_AUTH = ("admin", "public")
def parse_mosquitto_acl(acl_file_path):
rules = []
current_user = None
with open(acl_file_path) as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
if line.startswith('user '):
current_user = line.split()[1]
elif line.startswith('topic '):
parts = line.split()
if len(parts) == 2: # topic <topic>
access, topic = 'readwrite', parts[1]
else: # topic <access> <topic>
access, topic = parts[1], parts[2]
action_map = {
'read': 'subscribe',
'write': 'publish',
'readwrite': 'all',
'deny': 'all'
}
effect = 'deny' if access == 'deny' else 'allow'
rules.append({
'username': current_user,
'topic': topic,
'action': action_map.get(access, 'all'),
'effect': effect
})
return rules
def import_acl_rules(rules):
for rule in rules:
username = rule['username']
payload = {
'topic': rule['topic'],
'action': rule['action'],
'effect': rule['effect']
}
if username:
# 用户级规则
url = f"{ADMQ_URL}/api/v5/authorization/sources/built_in_database/rules/users/{username}"
else:
# 全局规则
url = f"{ADMQ_URL}/api/v5/authorization/sources/built_in_database/rules/all"
resp = requests.post(url, auth=ADMQ_AUTH, json=payload)
status = "✅" if resp.status_code in (200, 201) else "❌"
print(f"{status} 用户={username} 主题={rule['topic']} 动作={rule['action']}")
rules = parse_mosquitto_acl('/etc/mosquitto/acl')
import_acl_rules(rules)5.4 Mosquitto 集群迁移
Mosquitto 本身不支持原生集群,通常使用桥接(Bridge)实现多节点。
Mosquitto Bridge 配置(旧):
connection bridge-to-peer
address peer-host:1883
topic # both 1迁移到 ADMQ 后,可以直接使用 ADMQ 的原生集群功能,无需配置桥接,参见用户手册 - 集群部署章节。
6. 客户端代码迁移
6.1 连接地址更改
只需修改 Broker 地址,客户端代码无需其他变动(MQTT 协议兼容):
python
# 修改前(指向旧 Broker)
client.connect("old-broker.example.com", 1883)
# 修改后(指向 ADMQ)
client.connect("admq.example.com", 1883)6.2 WebSocket 路径
| Broker | WebSocket 路径 |
|---|---|
| Apusic ADMQ | ws://host:8083/mqtt |
| EMQX | ws://host:8083/mqtt |
| HiveMQ | ws://host:8083/mqtt |
| Mosquitto | ws://host:9001/ (通常无路径) |
Mosquitto WebSocket 迁移注意:
javascript
// Mosquitto WebSocket(旧)
const client = mqtt.connect('ws://old-broker:9001/', { ... });
// ADMQ WebSocket(新)— 注意路径变化
const client = mqtt.connect('ws://admq-host:8083/mqtt', { ... });6.3 HiveMQ Client SDK 迁移
如果使用 HiveMQ 官方 Java SDK,迁移到标准 Paho 客户端:
java
// HiveMQ SDK(旧)
Mqtt5Client client = Mqtt5Client.builder()
.serverHost("hivemq-host")
.serverPort(1883)
.build();
// Paho MQTT 5(新,连接 ADMQ)
MqttClient client = new MqttClient("tcp://admq-host:1883", "client-id");
MqttConnectionOptions opts = new MqttConnectionOptions();
// ... 设置选项
client.connect(opts);说明: ADMQ 完整支持 MQTT 5.0 协议,任何标准 MQTT 5.0 客户端库均可直接使用,无需特定 SDK。
7. 数据迁移
7.1 保留消息迁移
步骤1:从旧 Broker 导出保留消息
对于 EMQX:
bash
# 通过 REST API 获取保留消息
curl -u admin:public \
"http://old-emqx:18083/api/v5/retainer/messages?page=1&limit=10000" \
> retained_messages.json对于 Mosquitto / HiveMQ: 使用一个临时 MQTT 客户端订阅 # 主题(带保留标志),记录所有收到的保留消息:
python
import paho.mqtt.client as mqtt
import json
import time
retained = {}
def on_message(client, userdata, msg):
if msg.retain:
retained[msg.topic] = {
'payload': msg.payload.decode(errors='replace'),
'qos': msg.qos
}
print(f"收集保留消息: {msg.topic}")
client = mqtt.Client()
client.on_message = on_message
client.connect("old-broker", 1883)
client.subscribe("#", qos=1)
client.loop_start()
print("收集保留消息中,等待 10 秒...")
time.sleep(10)
client.loop_stop()
with open("retained_messages.json", "w") as f:
json.dump(retained, f, ensure_ascii=False, indent=2)
print(f"共收集 {len(retained)} 条保留消息")步骤2:将保留消息发布到 ADMQ
python
import paho.mqtt.client as mqtt
import json
with open("retained_messages.json") as f:
retained = json.load(f)
client = mqtt.Client()
client.username_pw_set("admin", "public")
client.connect("admq-host", 1883)
for topic, data in retained.items():
client.publish(
topic=topic,
payload=data['payload'],
qos=data['qos'],
retain=True # 重要:设置 retain=True
)
print(f"已发布保留消息: {topic}")
client.disconnect()
print(f"迁移完成,共 {len(retained)} 条")7.2 用户账号迁移
通用脚本(适用于任意来源的用户列表):
python
import requests
import csv
ADMQ_URL = "http://admq-host:18083"
ADMQ_AUTH = ("admin", "public")
def create_user(username, password):
"""在 ADMQ 创建内置数据库用户"""
resp = requests.post(
f"{ADMQ_URL}/api/v5/authentication/password_based:built_in_database/users",
auth=ADMQ_AUTH,
json={"user_id": username, "password": password}
)
return resp.status_code in (200, 201)
# 从 CSV 导入(格式:username,password)
with open("users.csv") as f:
reader = csv.DictReader(f)
success = 0
for row in reader:
if create_user(row['username'], row['password']):
print(f"✅ {row['username']}")
success += 1
else:
print(f"❌ {row['username']}")
print(f"\n导入完成: {success}/{reader.line_num - 1}")8. 迁移验证清单
迁移完成后,按以下清单逐项验证:
8.1 基础连通性
- [ ] TCP 1883 端口可以正常连接
- [ ] TLS 8883 端口可以正常连接(如已启用)
- [ ] WebSocket 8083 端口可以正常连接(如已启用)
- [ ] 管理控制台 18083 可以访问
8.2 认证验证
- [ ] 现有用户账号能正常登录
- [ ] 错误密码被正确拒绝(返回 CONNACK 5)
- [ ] 匿名访问策略与预期一致
8.3 功能验证
- [ ] QoS 0 消息正常发布和订阅
- [ ] QoS 1 消息正常发布和订阅,带确认
- [ ] QoS 2 消息正常发布和订阅,无重复
- [ ] 保留消息正常存储,新订阅者能收到
- [ ] 遗嘱消息在异常断开时正常触发
- [ ] 通配符
+和#订阅正常工作 - [ ] 共享订阅负载均衡正常工作
- [ ] 持久会话客户端离线消息正常投递
8.4 授权验证
- [ ] 有权限的发布操作正常成功
- [ ] 无权限的发布操作被正确拒绝
- [ ] 有权限的订阅操作正常成功
- [ ] 无权限的订阅操作被正确拒绝
8.5 性能验证
- [ ] 连接数达到预期峰值时系统稳定
- [ ] 消息延迟在可接受范围内
- [ ] CPU 和内存使用率正常
8.6 监控告警
- [ ] Prometheus 指标可以正常采集
- [ ] 关键指标告警配置正确
9. 常见迁移问题
Q1:客户端连接时报 "Client ID already in use"
原因: 两个 Broker 同时运行时,同一个 Client ID 已在旧 Broker 连接,切换到 ADMQ 时因 Client ID 重复被拒绝(如果同一客户端两端都连了)。
解决: 确保客户端先断开旧 Broker 再连接 ADMQ,或在灰度切换期间临时为 Client ID 添加后缀加以区分。
Q2:Mosquitto 的 allow_anonymous true 迁移后客户端无法连接
原因: ADMQ 默认启用认证,匿名连接被拒绝。
解决: 在 config/mqtt.conf 中注释掉或删除 authentication 配置块,或设置不带认证的来源:
ini
# 方法:直接允许所有连接(测试用)
authorization {
no_match = allow
}
# 同时删除 authentication 块Q3:从 Mosquitto 迁移后,WebSocket 连接的子协议不匹配
原因: Mosquitto WebSocket 默认不强制子协议,但 ADMQ 遵循 MQTT over WebSocket 规范,需要客户端在 WebSocket 握手时声明 mqtt 子协议。
解决: 确认客户端库配置中指定了子协议,例如在 MQTT.js 中:
javascript
mqtt.connect('ws://admq-host:8083/mqtt', {
// MQTT.js 会自动设置 mqtt 子协议
});Q4:HiveMQ 扩展(Extension)的功能无法迁移
HiveMQ 的部分扩展功能可以通过以下方式在 ADMQ 中实现:
| HiveMQ 扩展功能 | ADMQ 对应方案 |
|---|---|
| 自定义认证插件 | HTTP 认证后端 |
| 自定义授权插件 | HTTP 授权后端 |
| 消息转换 | 规则引擎(SQL) |
| 消息持久化 | 规则引擎 + 数据库桥接 |
| 自定义 Payload 处理 | gRPC Hooks(exhook) |
Q5:迁移后消息顺序与旧 Broker 不一致
MQTT 协议仅对同一主题的 QoS 1/2 消息保证顺序,不同主题之间不保证。如果业务依赖跨主题的消息顺序,需要在应用层通过时间戳或序列号处理。
Q6:如何实现零停机迁移
使用 DNS 切换方案:
- 在 ADMQ 上配置好所有认证和授权规则
- 将 Broker 的 DNS 记录 TTL 调低(如 60 秒)
- 修改 DNS 解析,将域名指向 ADMQ
- 等待客户端在心跳超时后自动重连到新 Broker
- 监控两端连接数,确认全部切换完成后下线旧 Broker
客户端需要配置自动重连(详见开发集成手册)。
如需迁移技术支持,请联系 Apusic 技术支持团队。