MQTT队列组件 (MQTT 5.0)
MQTT 5.0协议
:::success 版本提示
该功能自4.5.0版本开始可用 :::
🎯 组件概述
润典MQTT 5.0客户端组件是基于HiveMQ 1.3.7版本开发的商用级MQTT客户端,采用事件驱动架构设计,专门针对长时间断网后的快速恢复进行了深度优化。组件支持MQTT 5.0协议的所有新特性,包括会话过期、消息过期、主题别名、用户属性、遗嘱消息等。
主要特性
- ✅ 事件驱动架构: 基于Reactor响应式编程,支持事件流订阅和处理
- ✅ MQTT 5.0协议支持: 完整支持MQTT 5.0协议特性
- ✅ 快速恢复机制: 网络恢复后1秒内开始重连
- ✅ 多网络支持: 支持公网/VPC网络动态切换
- ✅ 手工初始化: 支持服务端配置下发初始化
- ✅ 会话保持: 断网期间保持会话状态和消息队列
- ✅ 智能监控: 网络连通性和连接状态实时监控
- ✅ 商用级稳定性: 针对生产环境优化的重连和错误处理
- ✅ 遗嘱消息支持: 设备异常离线时自动通知云端
🏗️ 架构设计
事件驱动架构
润典MQTT 5.0组件采用事件驱动架构设计,基于Reactor响应式编程模型,通过事件总线实现组件间的松耦合通信。这种架构设计具有以下优势:
- 松耦合设计: 组件间通过事件通信,减少直接依赖
- 响应式编程: 基于Reactor的Flux事件流,支持背压控制
- 职责分离: 技术异常自动处理,业务事件完全暴露给调用者
- 事件循环防护: 防止事件在组件内部形成循环
核心组件架构
事件流设计
连接状态事件流 (connectionStateFlow)
- 事件类型:
ConnectionStateEvent - 订阅目的: 监控连接状态变化,处理技术异常
- 事件内容: 连接状态、客户端ID、时间戳、原因码
- 处理策略:
- 技术异常(ABNORMAL_DISCONNECT、SESSION_EXPIRED)自动处理
- 业务事件(CONNECTED、DISCONNECTED等)暴露给调用者
消息事件流 (messageFlow)
- 事件类型:
MessageEvent - 订阅目的: 消息传递状态监控
- 事件内容: 消息ID、主题、QoS、时间戳、状态
- 处理策略: 完全暴露给调用者,支持业务逻辑处理
心跳事件流 (heartbeatFlow)
- 事件类型:
HeartbeatEvent - 订阅目的: 心跳状态监控
- 事件内容: 心跳时间、延迟、状态
- 处理策略: 内部监控使用,支持外部订阅
网络质量事件流 (networkQualityFlow)
- 事件类型:
NetworkQualityEvent - 订阅目的: 网络质量监控
- 事件内容: 延迟、丢包率、网络类型
- 处理策略: 内部网络管理,支持外部监控
组件生命周期
初始化阶段
- Spring自动注入: 组件被Spring容器管理
- 构造函数执行: 创建必要的管理器和客户端
- 配置验证: 验证MQTT服务器配置
- 服务初始化: 启动网络监控、连接监控等服务
- 事件订阅: 订阅必要的技术异常事件
运行维护阶段
- 连接管理: 维护MQTT连接状态,处理技术异常
- 消息处理: 处理消息发布、订阅、去重等
- 网络监控: 监控网络连通性,触发重连
- 心跳维护: 发送心跳消息,检测连接健康
- 事件发布: 发布各种状态事件,通知订阅者
清理销毁阶段
- 断开连接: 优雅断开MQTT连接
- 清理事件: 清理所有事件流和订阅
- 关闭服务: 关闭监控服务和线程池
- 资源释放: 释放所有占用的资源
各层职责说明
客户端层
- 应用层: 业务逻辑处理,消息格式转换
- 业务层: 消息路由、过滤、转换
- 配置层: 客户端配置管理,动态配置下发
连接层
- 网络监控: 实时检测网络连通性,5秒间隔检测
- 连接监控: 监控MQTT连接状态,10秒间隔检测
- 快速重连: 网络恢复后1秒内开始重连,最多10次快速重试
MQTT协议层
- 会话管理: MQTT 5.0会话过期机制,支持2小时会话保持
- 消息传递: QoS 0/1/2消息传递,支持消息过期机制
- 主题订阅: 支持主题别名,最大10个主题别名
润典MQTT组件实现
- HiveMqMqttClient: 基于HiveMQ 1.3.7的MQTT 5.0客户端实现
- 手工初始化接口: 支持服务端配置下发的手工初始化
- 网络切换机制: 支持公网/VPC网络动态切换
消息处理层
- 消息发布: 支持retained消息,消息重试机制
- 消息订阅: 支持批量订阅,主题监听器管理
- 消息过滤: 基于主题的消息过滤和路由
服务器层
- MQTT Broker: 支持MQTT 5.0协议的服务器
- 会话存储: 客户端会话状态持久化
- 消息队列: 离线消息队列管理
存储层
- 消息持久化: 重要消息本地持久化存储
- 会话状态: 客户端会话状态本地缓存
- 配置存储: 客户端配置信息本地存储
安全层
- 身份认证: 用户名密码认证机制
- 数据加密: TLS/SSL加密传输
- 访问控制: 基于主题的访问权限控制
消息发布方流程图
消息订阅方流程图
🔄 MQTT 5.0 vs 3.1.1协议对比
协议架构对比
MQTT 3.1.1 协议架构
MQTT 5.0 协议架构
功能特性对比
| 特性 | MQTT 3.1.1 | MQTT 5.0 | 优势说明 |
|---|---|---|---|
| 连接管理 | 基础连接选项 | 会话过期、连接原因码 | 更精确的连接状态控制 |
| 消息传递 | QoS 0/1/2 | QoS 0/1/2 + 消息过期 | 防止过期消息传递 |
| 主题订阅 | 基础订阅 | 主题别名、订阅选项 | 减少网络传输开销 |
| 用户属性 | 不支持 | 支持用户属性 | 更丰富的元数据传递 |
| 错误处理 | 基础错误码 | 详细错误码和原因字符串 | 更精确的错误诊断 |
| 流量控制 | 不支持 | 接收最大值控制 | 防止客户端过载 |
| 消息格式 | 固定格式 | 可变长度属性 | 更灵活的消息结构 |
弱网环境对比
| 场景 | MQTT 3.1.1 | MQTT 5.0 | 推荐方案 |
|---|---|---|---|
| 短期断网 | 自动重连 ⭐⭐ | 会话保持 + 自动重连 ⭐⭐⭐⭐⭐ | MQTT 5.0更优 |
| 长期断网 | 会话丢失 ⭐⭐⭐ | 会话过期机制 ⭐⭐⭐⭐⭐ | MQTT 5.0更优 |
| 网络切换 | 重新连接 ⭐⭐⭐ | 连接复用 ⭐⭐⭐⭐⭐ | MQTT 5.0更优 |
| 消息丢失 | 可能丢失 ⭐⭐⭐ | 消息过期保护 ⭐⭐⭐⭐⭐ | MQTT 5.0更优 |
| 网络效率 | 完整主题名传输 固定消息格式 无流量控制 ⭐⭐⭐ | 主题别名机制 可变长度属性 接收最大值控制 ⭐⭐⭐⭐⭐ | 减少60%传输开销 更灵活的消息格式 防止网络拥塞 MQTT 5.0更优 |
| 错误处理 | 基础错误码 简单认证失败 基础协议错误 ⭐⭐ | 详细错误码+原因字符串 详细认证原因+重试建议 详细协议错误+建议 ⭐⭐⭐⭐⭐ | 更精确的故障定位 更好的用户体验 更好的调试支持 MQTT 5.0更优 |
| 资源消耗 | 基础消息缓存 基础消息处理 固定格式传输 ⭐⭐⭐⭐⭐ | 会话状态+消息队列 消息去重+属性解析 优化传输但增加协议复杂度 ⭐⭐⭐ | 增加20-30%内存 增加15-25%CPU 减少40-60%带宽 MQTT 3.1.1更优 |
| 兼容性 | 所有MQTT服务器支持 所有MQTT客户端支持 成熟工具链 ⭐⭐⭐⭐⭐ | 部分服务器支持 需要5.0客户端 工具链正在完善 ⭐⭐⭐ | 3.1.1兼容性更广 5.0功能更强大 3.1.1生态更成熟 MQTT 3.1.1更优 |
升级前后对比
性能提升对比
| 性能指标 | MQTT 3.1.1 | MQTT 5.0 | 提升幅度 | 说明 |
|---|---|---|---|---|
| 连接恢复时间 | 30-60秒 | 1-3秒 | 95%+ | 网络恢复后快速重连 |
| 会话保持时间 | 无会话保持 | 2小时 | 100% | 断网期间保持会话状态 |
| 消息传递可靠性 | QoS 0/1/2 | QoS 0/1/2 + 消息过期 | 100% | 防止过期消息传递 |
| 网络切换时间 | 重新连接 | 连接复用 | 90%+ | 无需重新建立连接 |
| 错误诊断精度 | 基础错误码 | 详细错误码+原因字符串 | 300%+ | 更精确的故障定位 |
| 主题传输效率 | 完整主题名 | 主题别名 | 60%+ | 减少网络传输开销 |
| 流量控制能力 | 无控制机制 | 接收最大值控制 | 100% | 防止客户端过载 |
| 消息格式灵活性 | 固定格式 | 可变长度属性 | 200%+ | 更灵活的消息结构 |
商用环境对比
| 商用场景 | MQTT 3.1.1 | MQTT 5.0 | 商用价值 |
|---|---|---|---|
| 长时间断网恢复 | 需要重新连接和认证 | 会话保持,快速恢复 | 服务可用性提升95% |
| 网络质量不稳定 | 频繁断开重连 | 智能重连+会话保持 | 用户体验显著改善 |
| 大规模设备接入 | 连接管理复杂 | 流量控制+会话管理 | 系统稳定性提升 |
| 消息可靠性要求 | 可能丢失 | 消息过期+QoS保证 | 数据完整性保障 |
| 运维故障诊断 | 错误信息有限 | 详细错误码+原因 | 故障定位效率提升80% |
| 网络资源优化 | 固定开销 | 主题别名+流量控制 | 带宽利用率提升60% |
技术架构对比
| 架构特性 | MQTT 3.1.1 | MQTT 5.0 | 技术优势 |
|---|---|---|---|
| 协议扩展性 | 有限扩展 | 用户属性+可变格式 | 更好的协议扩展能力 |
| 连接管理 | 基础连接 | 会话过期+原因码 | 更精确的连接控制 |
| 消息传递 | 基础QoS | QoS+消息过期+优先级 | 更丰富的消息传递机制 |
| 错误处理 | 简单错误码 | 详细错误码+原因字符串 | 更完善的错误处理 |
| 流量控制 | 无控制机制 | 接收最大值+共享订阅 | 更智能的流量管理 |
| 会话管理 | Clean Session | 会话过期+状态保持 | 更灵活的会话管理 |
升级收益总结
性能提升:
- ✅ 连接恢复时间从30-60秒降低到1-3秒,提升95%+
- ✅ 会话保持时间从0提升到2小时,实现100%会话保持
- ✅ 网络切换时间减少90%+,支持连接复用
- ✅ 错误诊断精度提升300%+,支持详细错误码
商用价值:
- ✅ 服务可用性提升95%,支持长时间断网快速恢复
- ✅ 用户体验显著改善,减少网络不稳定影响
- ✅ 系统稳定性提升,支持大规模设备接入
- ✅ 数据完整性保障,防止消息丢失
技术优势:
- ✅ 协议扩展性更强,支持用户属性和可变格式
- ✅ 连接控制更精确,支持会话过期和原因码
- ✅ 消息传递机制更丰富,支持消息过期和优先级
- ✅ 错误处理更完善,支持详细错误诊断
🌐 弱网环境优化
网络监控与快速恢复原理
网络监控架构
快速重连机制
监控服务架构
网络监控机制
// 网络连通性检测
private boolean checkNetworkConnectivity() {
try {
String host = this.networkType == NetworkTypeEnum.PUBLIC ?
properties.getServer().getHost() : properties.getServer().getVpcHost();
int port = this.networkType == NetworkTypeEnum.PUBLIC ?
properties.getServer().getPort() : properties.getServer().getVpcPort();
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), 3000);
networkAvailable.set(true);
return true;
}
} catch (IOException e) {
networkAvailable.set(false);
return false;
}
}
快速重连机制
// 快速重连配置
private static final long FAST_RECONNECT_INTERVAL_MS = 1000L; // 1秒重连间隔
private static final int MAX_FAST_RECONNECT_ATTEMPTS = 10; // 最多10次重试
private static final long SESSION_EXPIRY_INTERVAL = 7200L; // 2小时会话保持
// 监控服务配置
private static final long NETWORK_CHECK_INTERVAL = 5L; // 网络检测间隔5秒
private static final long CONNECTION_MONITOR_INTERVAL = 10L; // 连接监控间隔10秒
private static final int KEEP_ALIVE_INTERVAL = 30; // 心跳间隔30秒
监控服务配置
// 网络监控服务 - 5秒间隔
networkMonitorService.scheduleWithFixedDelay(() -> {
boolean networkOk = checkNetworkConnectivity();
if (networkOk && !isConnected.get()) {
fastReconnectWithRetry();
}
}, 0, 5, TimeUnit.SECONDS);
// 连接监控服务 - 10秒间隔
connectionMonitorService.scheduleWithFixedDelay(() -> {
if (mqttClient.getState() != MqttClientState.CONNECTED) {
fastReconnectWithRetry();
}
}, 0, 10, TimeUnit.SECONDS);
// 心跳服务 - 30秒间隔
heartbeatService.scheduleWithFixedDelay(() -> {
if (isConnected.get()) {
sendKeepAlive();
}
}, 0, 30, TimeUnit.SECONDS);
💀 遗嘱消息支持
遗嘱消息概述
遗嘱消息(Last Will and Testament, LWT)是MQTT协议的重要特性。当客户端异常断开连接时,服务器会自动发布预设的遗嘱消息,便于云端及时感知设备离线。
工作原理
KDS Box 场景业务价值
- 实时监控KDS Box在线状态
- 设备异常离线时立即通知
- 提升门店运维效率
遗嘱消息配置代码示例
连接配置片段
// Mqtt5Config 配置类中的遗嘱消息配置
@ConfigurationProperties(prefix = "platform.component.mqtt.mqtt5")
public class Mqtt5Config {
/**
* 是否启用遗嘱消息
*/
private boolean enableWillMessage = true;
/**
* 遗嘱消息主题
*/
private String willTopic = "device/status/{clientId}";
/**
* 遗嘱消息内容
*/
private String willMessage = "异常断开连接";
/**
* 遗嘱消息上报的App版本号
*/
private String appVersion = "";
/**
* 门店ID(可选参数)
*/
private String storeId = "";
}
遗嘱消息构建
// 构建遗嘱消息内容
private String buildWillMessage() {
try {
Map<String, Object> willMessage = new HashMap<>();
willMessage.put("deviceId", clientId);
willMessage.put("status", "offline");
willMessage.put("timestamp", System.currentTimeMillis());
willMessage.put("reason", "abnormal_disconnect");
willMessage.put("networkType", this.networkType.name());
willMessage.put("groupId", this.properties.getGroupId());
willMessage.put("deviceType", "KDS_BOX");
// 添加可选的App版本和门店ID
if (StringUtils.isNotBlank(properties.getMqtt5().getAppVersion())) {
willMessage.put("appVersion", properties.getMqtt5().getAppVersion());
}
if (StringUtils.isNotBlank(properties.getMqtt5().getStoreId())) {
willMessage.put("storeId", properties.getMqtt5().getStoreId());
}
return JsonUtils.getInstance().serialize(willMessage);
} catch (Exception e) {
log.error("构建遗嘱消息失败: {}", e.getMessage());
return "{\"deviceId\":\"%s\",\"status\":\"offline\"}".formatted(clientId);
}
}
云端处理建议
- 订阅
device/status/+主题,解析遗嘱消息,及时更新设备状态并触发告警。 - 根据
storeId字段进行门店级别的状态管理 - 利用
appVersion字段进行版本兼容性检查
🚀 快速上手指南
1. 添加依赖
<dependency>
<groupId>cn.com.rydeen</groupId>
<artifactId>rydeen-component-mqtt</artifactId>
<version>${rydeen.version}</version>
</dependency>
2. 配置文件
platform:
component:
mqtt:
enable: true
mqtt-version: mqtt_5_0 # 使用MQTT 5.0协议
client-type: CLIENT
parent-topic: /rydeen
group-id: your-group-id
heartbeat-interval: 30 # 心跳间隔30秒
server:
host: your-mqtt-server.com
port: 1883
vpc-host: your-vpc-server.com
vpc-port: 1883
username: your-username
password: your-password
default-network-type: PUBLIC
qos: 1
time-to-wait: 10000
# MQTT 5.0 专用配置
mqtt5:
client-type: "pos_terminal"
clean-start: false
session-expiry-interval: 1800 # 30分钟会话过期
message-expiry-interval: 1800 # 30分钟消息过期
connection-timeout: 30
enable-will-message: true
will-topic: "device/status/{clientId}"
will-message: "异常断开连接"
app-version: "1.0.0"
store-id: "STORE_001"
enable-user-properties: true
enable-message-priority: false
enable-message-delay: false
message-delay-interval: 0
# 快速恢复配置
fast-recovery:
enabled: true # 是否启用快速恢复模式
network-check-interval: 5 # 网络检测间隔(秒)
connection-monitor-interval: 10 # 连接状态监控间隔(秒)
fast-reconnect-interval: 1000 # 快速重连间隔(毫秒)
max-fast-reconnect-attempts: 10 # 最大快速重连次数
network-connect-timeout: 3000 # 网络连接超时(毫秒)
keep-alive-interval: 30 # 心跳间隔(秒)
enable-network-monitor: true # 是否启用网络监控
enable-connection-monitor: true # 是否启用连接状态监控
enable-fast-reconnect: true # 是否启用快速重连
reconnect-on-network-recovery: true # 网络恢复后立即重连
reconnect-on-disconnect: true # 连接断开后立即重连
3. 基础使用
@Autowired
private HiveMqMqttClient mqttClient;
// 发布消息
mqttClient.doPublish("/test/topic", "Hello MQTT 5.0".getBytes());
// 发布保留消息
mqttClient.doPublish("/test/topic", "Retained message".getBytes(), true);
// 订阅消息
mqttClient.registerConsumer("/test/topic", message -> {
System.out.println("收到消息: " + new String(message.getPayload()));
System.out.println("消息主题: " + message.getTopic());
System.out.println("消息QoS: " + message.getQos());
});
4. 事件订阅
// 订阅连接状态事件
MqttEventBus.connectionStateFlow
.filter(event -> event.getState() == ConnectionState.CONNECTED)
.subscribe(event -> {
log.info("MQTT连接已建立,网络类型: {}", event.getNetworkType());
});
// 订阅网络质量事件
MqttEventBus.networkQualityFlow
.filter(event -> event.getStats().getAverageLatency() > 100)
.subscribe(event -> {
log.warn("网络延迟较高: {}ms", event.getStats().getAverageLatency());
});
// 订阅心跳事件
MqttEventBus.heartbeatFlow
.subscribe(event -> {
log.debug("心跳状态: {}, 延迟: {}ms", event.getStatus(), event.getLatency());
});
5. 手工初始化
// 通过服务接口获取配置
MqttServerInfo serverInfo = getServerConfigFromApi();
mqttClient.initialClient(serverInfo);
// 动态切换服务器
mqttClient.changeServer(NetworkTypeEnum.VPC, "new-host", 1883);
// 切换网络类型
mqttClient.changeServer(NetworkTypeEnum.VPC);
6. 高级配置示例
生产环境配置
platform:
component:
mqtt:
fast-recovery:
enabled: true
network-check-interval: 3 # 3秒网络检测
connection-monitor-interval: 5 # 5秒连接监控
fast-reconnect-interval: 500 # 500ms快速重连
max-fast-reconnect-attempts: 15 # 15次重连尝试
network-connect-timeout: 5000 # 5秒连接超时
keep-alive-interval: 20 # 20秒心跳间隔
开发环境配置
platform:
component:
mqtt:
fast-recovery:
enabled: true
network-check-interval: 10 # 10秒网络检测
connection-monitor-interval: 20 # 20秒连接监控
fast-reconnect-interval: 2000 # 2秒快速重连
max-fast-reconnect-attempts: 5 # 5次重连尝试
network-connect-timeout: 10000 # 10秒连接超时
keep-alive-interval: 60 # 60秒心跳间隔
弱网环境配置
platform:
component:
mqtt:
fast-recovery:
enabled: true
network-check-interval: 2 # 2秒网络检测
connection-monitor-interval: 3 # 3秒连接监控
fast-reconnect-interval: 200 # 200ms快速重连
max-fast-reconnect-attempts: 20 # 20次重连尝试
network-connect-timeout: 8000 # 8秒连接超时
keep-alive-interval: 15 # 15秒心跳间隔
reconnect-on-network-recovery: true
reconnect-on-disconnect: true
📚 接口详细说明
事件订阅与处理
连接状态事件处理
@Component
public class ConnectionEventHandler {
@PostConstruct
public void init() {
// 订阅连接状态事件
MqttEventBus.connectionStateFlow
.filter(event -> event.getState() == ConnectionState.CONNECTED)
.subscribe(this::handleConnected);
MqttEventBus.connectionStateFlow
.filter(event -> event.getState() == ConnectionState.DISCONNECTED)
.subscribe(this::handleDisconnected);
MqttEventBus.connectionStateFlow
.filter(event -> event.getState() == ConnectionState.ABNORMAL_DISCONNECT)
.subscribe(this::handleAbnormalDisconnect);
}
private void handleConnected(ConnectionStateEvent event) {
log.info("MQTT连接已建立 - 客户端ID: {}, 网络类型: {}, 时间: {}",
event.getClientId(), event.getNetworkType(), event.getTimestamp());
// 连接成功后重新注册所有监听器
reRegisterAllListeners();
}
private void handleDisconnected(ConnectionStateEvent event) {
log.info("MQTT连接已断开 - 客户端ID: {}, 原因: {}, 时间: {}",
event.getClientId(), event.getReason(), event.getTimestamp());
// 更新UI状态
updateConnectionStatus(false);
}
private void handleAbnormalDisconnect(ConnectionStateEvent event) {
log.warn("MQTT连接异常断开 - 客户端ID: {}, 原因: {}, 时间: {}",
event.getClientId(), event.getReason(), event.getTimestamp());
// 触发告警
triggerConnectionAlert(event);
}
}
网络质量事件处理
@Component
public class NetworkQualityHandler {
@PostConstruct
public void init() {
// 订阅网络质量事件
MqttEventBus.networkQualityFlow
.filter(event -> event.getStats().getAverageLatency() > 100)
.subscribe(this::handleHighLatency);
MqttEventBus.networkQualityFlow
.filter(event -> event.getStats().getPacketLossRate() > 0.1)
.subscribe(this::handleHighPacketLoss);
}
private void handleHighLatency(NetworkQualityEvent event) {
NetworkQualityStats stats = event.getStats();
log.warn("网络延迟较高 - 平均延迟: {}ms, 最大延迟: {}ms, 时间: {}",
stats.getAverageLatency(), stats.getMaxLatency(), event.getTimestamp());
// 考虑切换到VPC网络
if (stats.getAverageLatency() > 200) {
considerNetworkSwitch();
}
}
private void handleHighPacketLoss(NetworkQualityEvent event) {
NetworkQualityStats stats = event.getStats();
log.error("网络丢包率较高 - 丢包率: {}%, 时间: {}",
stats.getPacketLossRate() * 100, event.getTimestamp());
// 触发网络质量告警
triggerNetworkQualityAlert(event);
}
}
心跳事件处理
@Component
public class HeartbeatHandler {
@PostConstruct
public void init() {
// 订阅心跳事件
MqttEventBus.heartbeatFlow
.filter(event -> event.getStatus() == HeartbeatStatus.FAILED)
.subscribe(this::handleHeartbeatFailure);
MqttEventBus.heartbeatFlow
.filter(event -> event.getLatency() > 1000)
.subscribe(this::handleHighHeartbeatLatency);
}
private void handleHeartbeatFailure(HeartbeatEvent event) {
log.warn("心跳失败 - 延迟: {}ms, 时间: {}",
event.getLatency(), event.getTimestamp());
// 检查连接状态
checkConnectionHealth();
}
private void handleHighHeartbeatLatency(HeartbeatEvent event) {
log.warn("心跳延迟较高 - 延迟: {}ms, 时间: {}",
event.getLatency(), event.getTimestamp());
// 记录性能指标
recordPerformanceMetrics(event);
}
}
消息发布与订阅流程图
消息发布方流程
消息订阅方流程
公共接口方法
1. initialClient(MqttServerInfo serverInfo)
用途: 手工初始化MQTT客户端 参数: 包含完整服务器配置信息的对象 功能:
- 设置服务器地址(公网/VPC)
- 配置认证信息(用户名/密码)
- 设置设备ID和分组ID
- 配置网络类型和服务器类型
- 自动启动连接服务
调用场景:
- 客户端启动时通过服务接口获取配置
- 配置变更时重新初始化
- 网络切换时重新配置
使用示例:
@Service
public class MqttConfigService {
@Autowired
private HiveMqMqttClient mqttClient;
public void updateMqttConfig() {
// 从配置服务获取最新配置
MqttServerInfo serverInfo = getLatestServerConfig();
// 手工初始化客户端
mqttClient.initialClient(serverInfo);
log.info("MQTT客户端配置已更新");
}
private MqttServerInfo getLatestServerConfig() {
// 调用配置服务API获取最新配置
return configApiService.getMqttServerConfig();
}
}
2. initialClient(MqttServerInfo serverInfo, boolean enable)
用途: 带启用标志的手工初始化 参数: 服务器配置信息 + 是否启用标志 功能: 可以控制是否立即启用MQTT连接
调用场景:
- 需要延迟启动的场景
- 配置验证后决定是否启用
使用示例:
@Service
public class MqttInitializationService {
@Autowired
private HiveMqMqttClient mqttClient;
public void initializeWithValidation(MqttServerInfo serverInfo) {
// 验证配置
if (validateServerConfig(serverInfo)) {
// 配置验证通过,启用连接
mqttClient.initialClient(serverInfo, true);
log.info("MQTT客户端已启用");
} else {
// 配置验证失败,不启用连接
mqttClient.initialClient(serverInfo, false);
log.warn("MQTT客户端配置验证失败,连接未启用");
}
}
private boolean validateServerConfig(MqttServerInfo serverInfo) {
// 配置验证逻辑
return serverInfo != null &&
StringUtils.isNotBlank(serverInfo.getHost()) &&
serverInfo.getPort() > 0;
}
}
3. changeServer(NetworkTypeEnum networkType, String host, int port)
用途: 动态切换服务器地址 参数: 网络类型 + 新主机地址 + 端口 功能: 运行时更换MQTT服务器
调用场景:
- 服务器地址变更
- 负载均衡切换
- 故障转移
使用示例:
@Service
public class ServerSwitchService {
@Autowired
private HiveMqMqttClient mqttClient;
public void switchToBackupServer() {
// 切换到备用服务器
mqttClient.changeServer(NetworkTypeEnum.PUBLIC, "backup.example.com", 1883);
log.info("已切换到备用服务器");
}
public void switchToLoadBalancedServer(String host, int port) {
// 切换到负载均衡服务器
mqttClient.changeServer(NetworkTypeEnum.VPC, host, port);
log.info("已切换到负载均衡服务器: {}:{}", host, port);
}
}
4. changeServer(NetworkTypeEnum networkType)
用途: 切换网络类型 参数: 目标网络类型 功能: 在已配置的服务器间切换
调用场景:
- 公网/VPC网络切换
- 网络质量优化
使用示例:
@Service
public class NetworkOptimizationService {
@Autowired
private HiveMqMqttClient mqttClient;
public void optimizeNetworkConnection() {
// 获取当前网络质量
NetworkQualityStats stats = getCurrentNetworkQuality();
if (stats.getAverageLatency() > 200) {
// 网络延迟较高,切换到VPC网络
mqttClient.changeServer(NetworkTypeEnum.VPC);
log.info("网络延迟较高,已切换到VPC网络");
} else if (stats.getAverageLatency() < 50) {
// 网络质量良好,切换到公网
mqttClient.changeServer(NetworkTypeEnum.PUBLIC);
log.info("网络质量良好,已切换到公网");
}
}
private NetworkQualityStats getCurrentNetworkQuality() {
// 获取当前网络质量统计
return networkQualityService.getCurrentStats();
}
}
5. doPublish(String topic, byte[] value)
用途: 发布消息 参数: 主题 + 消息内容 功能: 向指定主题发布消息
调用场景:
- 业务消息发布
- 状态上报
- 命令下发
使用示例:
@Service
public class MessagePublishService {
@Autowired
private HiveMqMqttClient mqttClient;
public void publishDeviceStatus(String deviceId, DeviceStatus status) {
String topic = String.format("/device/%s/status", deviceId);
String message = JsonUtils.toJson(status);
try {
mqttClient.doPublish(topic, message.getBytes());
log.info("设备状态已发布 - 设备ID: {}, 主题: {}", deviceId, topic);
} catch (Exception e) {
log.error("发布设备状态失败 - 设备ID: {}, 错误: {}", deviceId, e.getMessage());
}
}
public void publishCommand(String deviceId, DeviceCommand command) {
String topic = String.format("/device/%s/command", deviceId);
String message = JsonUtils.toJson(command);
try {
mqttClient.doPublish(topic, message.getBytes());
log.info("设备命令已发布 - 设备ID: {}, 主题: {}", deviceId, topic);
} catch (Exception e) {
log.error("发布设备命令失败 - 设备ID: {}, 错误: {}", deviceId, e.getMessage());
}
}
}
6. doPublish(String topic, byte[] value, boolean retained)
用途: 发布保留消息 参数: 主题 + 消息内容 + 是否保留 功能: 发布在服务器保留的消息
调用场景:
- 设备状态保留
- 配置信息保留
- 最后已知状态
使用示例:
@Service
public class RetainedMessageService {
@Autowired
private HiveMqMqttClient mqttClient;
public void publishDeviceLastKnownStatus(String deviceId, DeviceStatus status) {
String topic = String.format("/device/%s/last-known-status", deviceId);
String message = JsonUtils.toJson(status);
// 发布保留消息,新连接的客户端可以立即获取最后状态
mqttClient.doPublish(topic, message.getBytes(), true);
log.info("设备最后状态已保留 - 设备ID: {}, 主题: {}", deviceId, topic);
}
public void publishConfiguration(String configId, Configuration config) {
String topic = String.format("/config/%s", configId);
String message = JsonUtils.toJson(config);
// 发布保留消息,新连接的客户端可以立即获取配置
mqttClient.doPublish(topic, message.getBytes(), true);
log.info("配置信息已保留 - 配置ID: {}, 主题: {}", configId, topic);
}
}
7. registerConsumer(String topic, Consumer<ConsumerMessage> callback)
用途: 注册消息监听器 参数: 主题 + 回调函数 功能: 订阅主题并处理接收到的消息
调用场景:
- 业务消息处理
- 命令接收
- 状态监听
使用示例:
@Component
public class MessageConsumerService {
@Autowired
private HiveMqMqttClient mqttClient;
@PostConstruct
public void init() {
// 注册设备命令监听器
mqttClient.registerConsumer("/device/+/command", this::handleDeviceCommand);
// 注册设备配置更新监听器
mqttClient.registerConsumer("/device/+/config", this::handleDeviceConfig);
// 注册系统通知监听器
mqttClient.registerConsumer("/system/notification", this::handleSystemNotification);
}
private void handleDeviceCommand(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析设备命令
DeviceCommand command = JsonUtils.fromJson(payload, DeviceCommand.class);
// 处理设备命令
processDeviceCommand(command);
log.info("设备命令已处理 - 主题: {}, 命令: {}", topic, command);
} catch (Exception e) {
log.error("处理设备命令失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
private void handleDeviceConfig(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析设备配置
DeviceConfig config = JsonUtils.fromJson(payload, DeviceConfig.class);
// 应用设备配置
applyDeviceConfig(config);
log.info("设备配置已更新 - 主题: {}, 配置: {}", topic, config);
} catch (Exception e) {
log.error("处理设备配置失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
private void handleSystemNotification(ConsumerMessage message) {
try {
String payload = new String(message.getPayload());
// 解析系统通知
SystemNotification notification = JsonUtils.fromJson(payload, SystemNotification.class);
// 处理系统通知
processSystemNotification(notification);
log.info("系统通知已处理 - 通知: {}", notification);
} catch (Exception e) {
log.error("处理系统通知失败 - 错误: {}", e.getMessage());
}
}
}
8. unregisterConsumer(String topic)
用途: 取消消息监听器 参数: 主题 功能: 取消订阅指定主题
调用场景:
- 动态取消订阅
- 资源清理
- 权限变更
使用示例:
@Service
public class ConsumerManagementService {
@Autowired
private HiveMqMqttClient mqttClient;
private final Set<String> activeSubscriptions = new ConcurrentHashSet<>();
public void addSubscription(String topic, Consumer<ConsumerMessage> callback) {
mqttClient.registerConsumer(topic, callback);
activeSubscriptions.add(topic);
log.info("已添加订阅 - 主题: {}", topic);
}
public void removeSubscription(String topic) {
mqttClient.unregisterConsumer(topic);
activeSubscriptions.remove(topic);
log.info("已移除订阅 - 主题: {}", topic);
}
public void removeAllSubscriptions() {
for (String topic : activeSubscriptions) {
mqttClient.unregisterConsumer(topic);
}
activeSubscriptions.clear();
log.info("已移除所有订阅");
}
public Set<String> getActiveSubscriptions() {
return new HashSet<>(activeSubscriptions);
}
}
9. reinitialize()
用途: 重新初始化客户端 功能: 重新建立MQTT连接
调用场景:
- 连接异常恢复
- 配置重大变更
- 故障排除
使用示例:
@Service
public class ClientRecoveryService {
@Autowired
private HiveMqMqttClient mqttClient;
public void recoverClient() {
try {
log.info("开始重新初始化MQTT客户端");
// 重新初始化客户端
mqttClient.reinitialize();
log.info("MQTT客户端重新初始化完成");
} catch (Exception e) {
log.error("MQTT客户端重新初始化失败: {}", e.getMessage());
// 延迟重试
scheduleRetry();
}
}
private void scheduleRetry() {
// 延迟5秒后重试
CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS)
.execute(this::recoverClient);
}
}
自动处理方法
1. 网络监控
触发: 每5秒自动检测 功能:
- 检测网络连通性
- 网络恢复时自动重连
- 更新网络状态标志
监控逻辑:
// 网络监控服务 - 5秒间隔
networkMonitorService.scheduleWithFixedDelay(() -> {
boolean networkOk = checkNetworkConnectivity();
if (networkOk && !isConnected.get()) {
fastReconnectWithRetry();
}
}, 0, 5, TimeUnit.SECONDS);
2. 连接监控
触发: 每10秒自动检测 功能:
- 监控MQTT连接状态
- 连接断开时自动重连
- 维护连接状态标志
监控逻辑:
// 连接监控服务 - 10秒间隔
connectionMonitorService.scheduleWithFixedDelay(() -> {
if (mqttClient.getState() != MqttClientState.CONNECTED) {
fastReconnectWithRetry();
}
}, 0, 10, TimeUnit.SECONDS);
3. 快速重连
触发: 网络恢复或连接断开时 功能:
- 1秒内开始重连
- 最多10次快速重试
- 保持会话状态
重连逻辑:
// 快速重连配置
private static final long FAST_RECONNECT_INTERVAL_MS = 1000L; // 1秒重连间隔
private static final int MAX_FAST_RECONNECT_ATTEMPTS = 10; // 最多10次重试
private static final long SESSION_EXPIRY_INTERVAL = 7200L; // 2小时会话保持
4. 心跳维护
触发: 定时任务 功能:
- 发送心跳消息
- 检测连接健康状态
- 维护连接活跃度
心跳逻辑:
// 心跳服务 - 30秒间隔
heartbeatService.scheduleWithFixedDelay(() -> {
if (isConnected.get()) {
sendKeepAlive();
}
}, 0, 30, TimeUnit.SECONDS);
5. 消息处理
触发: 收到MQTT消息时 功能:
- 消息格式转换
- 调用注册的回调函数
- 错误处理和日志记录
处理逻辑:
// 消息处理流程
private void handleMessage(Mqtt5Publish message) {
try {
// 消息去重检查
if (isDuplicateMessage(message)) {
log.debug("收到重复消息,已丢弃");
return;
}
// 保存消息到缓存
saveMessageToCache(message);
// 转发给业务处理器
forwardToBusinessHandler(message);
} catch (Exception e) {
log.error("处理消息失败: {}", e.getMessage());
}
}
📋 使用场景示例
场景1: 设备状态上报
设备状态上报架构
完整实现代码
@Service
public class DeviceStatusService {
@Autowired
private HiveMqMqttClient mqttClient;
private final Map<String, DeviceStatus> deviceStatusCache = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
// 注册设备命令监听器
mqttClient.registerConsumer("/device/+/command", this::handleDeviceCommand);
// 注册设备配置更新监听器
mqttClient.registerConsumer("/device/+/config", this::handleDeviceConfig);
}
/**
* 上报设备状态
*/
public void reportDeviceStatus(String deviceId, DeviceStatus status) {
try {
// 更新本地缓存
deviceStatusCache.put(deviceId, status);
// 构建状态消息
DeviceStatusMessage statusMessage = DeviceStatusMessage.builder()
.deviceId(deviceId)
.status(status)
.timestamp(System.currentTimeMillis())
.version("1.0.0")
.build();
// 发布状态消息
String topic = String.format("/device/%s/status", deviceId);
String message = JsonUtils.toJson(statusMessage);
mqttClient.doPublish(topic, message.getBytes());
log.info("设备状态已上报 - 设备ID: {}, 状态: {}", deviceId, status);
} catch (Exception e) {
log.error("上报设备状态失败 - 设备ID: {}, 错误: {}", deviceId, e.getMessage());
throw new DeviceStatusException("上报设备状态失败", e);
}
}
/**
* 上报设备心跳
*/
public void reportDeviceHeartbeat(String deviceId) {
try {
DeviceHeartbeatMessage heartbeatMessage = DeviceHeartbeatMessage.builder()
.deviceId(deviceId)
.timestamp(System.currentTimeMillis())
.uptime(getDeviceUptime(deviceId))
.build();
String topic = String.format("/device/%s/heartbeat", deviceId);
String message = JsonUtils.toJson(heartbeatMessage);
mqttClient.doPublish(topic, message.getBytes());
log.debug("设备心跳已上报 - 设备ID: {}", deviceId);
} catch (Exception e) {
log.error("上报设备心跳失败 - 设备ID: {}, 错误: {}", deviceId, e.getMessage());
}
}
/**
* 处理设备命令
*/
private void handleDeviceCommand(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析设备命令
DeviceCommand command = JsonUtils.fromJson(payload, DeviceCommand.class);
// 验证命令
if (validateDeviceCommand(command)) {
// 执行设备命令
executeDeviceCommand(command);
// 发送命令确认
sendCommandAck(command.getDeviceId(), command.getCommandId(), true);
log.info("设备命令已执行 - 设备ID: {}, 命令: {}",
command.getDeviceId(), command.getCommandType());
} else {
// 发送命令拒绝
sendCommandAck(command.getDeviceId(), command.getCommandId(), false);
log.warn("设备命令验证失败 - 设备ID: {}, 命令: {}",
command.getDeviceId(), command.getCommandType());
}
} catch (Exception e) {
log.error("处理设备命令失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 处理设备配置更新
*/
private void handleDeviceConfig(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析设备配置
DeviceConfig config = JsonUtils.fromJson(payload, DeviceConfig.class);
// 应用设备配置
applyDeviceConfig(config);
log.info("设备配置已更新 - 主题: {}, 配置: {}", topic, config);
} catch (Exception e) {
log.error("处理设备配置失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 获取设备状态
*/
public DeviceStatus getDeviceStatus(String deviceId) {
return deviceStatusCache.get(deviceId);
}
/**
* 获取所有设备状态
*/
public Map<String, DeviceStatus> getAllDeviceStatus() {
return new HashMap<>(deviceStatusCache);
}
// 其他辅助方法...
private boolean validateDeviceCommand(DeviceCommand command) {
// 命令验证逻辑
return command != null &&
StringUtils.isNotBlank(command.getDeviceId()) &&
StringUtils.isNotBlank(command.getCommandType());
}
private void executeDeviceCommand(DeviceCommand command) {
// 命令执行逻辑
switch (command.getCommandType()) {
case "RESTART":
restartDevice(command.getDeviceId());
break;
case "UPDATE_CONFIG":
updateDeviceConfig(command.getDeviceId(), command.getParameters());
break;
case "DIAGNOSTIC":
runDeviceDiagnostic(command.getDeviceId());
break;
default:
log.warn("未知的设备命令类型: {}", command.getCommandType());
}
}
private void sendCommandAck(String deviceId, String commandId, boolean success) {
try {
CommandAckMessage ackMessage = CommandAckMessage.builder()
.deviceId(deviceId)
.commandId(commandId)
.success(success)
.timestamp(System.currentTimeMillis())
.build();
String topic = String.format("/device/%s/command/ack", deviceId);
String message = JsonUtils.toJson(ackMessage);
mqttClient.doPublish(topic, message.getBytes());
} catch (Exception e) {
log.error("发送命令确认失败 - 设备ID: {}, 命令ID: {}, 错误: {}",
deviceId, commandId, e.getMessage());
}
}
}
场景2: 动态配置下发
配置下发流程
完整实现代码
@Service
public class DynamicConfigService {
@Autowired
private HiveMqMqttClient mqttClient;
@Autowired
private NetworkQualityService networkQualityService;
private final Map<String, Object> currentConfig = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
// 注册配置更新监听器
mqttClient.registerConsumer("/config/+/update", this::handleConfigUpdate);
// 注册配置查询监听器
mqttClient.registerConsumer("/config/+/query", this::handleConfigQuery);
// 启动配置监控
startConfigMonitoring();
}
/**
* 更新MQTT服务器配置
*/
public void updateMqttServerConfig() {
try {
// 从配置服务获取最新配置
MqttServerInfo newConfig = getLatestMqttConfig();
// 验证新配置
if (validateMqttConfig(newConfig)) {
// 测试新配置连接
if (testMqttConnection(newConfig)) {
// 应用新配置
applyMqttConfig(newConfig);
log.info("MQTT服务器配置已更新");
} else {
log.error("新MQTT配置连接测试失败");
}
} else {
log.error("新MQTT配置验证失败");
}
} catch (Exception e) {
log.error("更新MQTT服务器配置失败: {}", e.getMessage());
}
}
/**
* 网络质量优化
*/
public void optimizeNetworkConnection() {
try {
// 获取当前网络质量
NetworkQualityStats stats = networkQualityService.getCurrentStats();
if (stats.getAverageLatency() > 200) {
// 网络延迟较高,切换到VPC网络
switchToVpcNetwork();
log.info("网络延迟较高,已切换到VPC网络");
} else if (stats.getAverageLatency() < 50) {
// 网络质量良好,切换到公网
switchToPublicNetwork();
log.info("网络质量良好,已切换到公网");
}
} catch (Exception e) {
log.error("网络连接优化失败: {}", e.getMessage());
}
}
/**
* 处理配置更新
*/
private void handleConfigUpdate(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析配置更新
ConfigUpdateMessage configUpdate = JsonUtils.fromJson(payload, ConfigUpdateMessage.class);
// 验证配置更新
if (validateConfigUpdate(configUpdate)) {
// 应用配置更新
applyConfigUpdate(configUpdate);
// 发送配置确认
sendConfigAck(configUpdate.getConfigId(), true);
log.info("配置更新已应用 - 配置ID: {}, 类型: {}",
configUpdate.getConfigId(), configUpdate.getConfigType());
} else {
// 发送配置拒绝
sendConfigAck(configUpdate.getConfigId(), false);
log.warn("配置更新验证失败 - 配置ID: {}", configUpdate.getConfigId());
}
} catch (Exception e) {
log.error("处理配置更新失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 处理配置查询
*/
private void handleConfigQuery(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析配置查询
ConfigQueryMessage configQuery = JsonUtils.fromJson(payload, ConfigQueryMessage.class);
// 获取配置信息
Object config = getConfig(configQuery.getConfigKey());
// 发送配置响应
sendConfigResponse(configQuery.getQueryId(), config);
log.debug("配置查询已响应 - 查询ID: {}, 配置键: {}",
configQuery.getQueryId(), configQuery.getConfigKey());
} catch (Exception e) {
log.error("处理配置查询失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 切换到VPC网络
*/
private void switchToVpcNetwork() {
try {
mqttClient.changeServer(NetworkTypeEnum.VPC);
// 更新网络类型配置
updateNetworkTypeConfig(NetworkTypeEnum.VPC);
} catch (Exception e) {
log.error("切换到VPC网络失败: {}", e.getMessage());
}
}
/**
* 切换到公网
*/
private void switchToPublicNetwork() {
try {
mqttClient.changeServer(NetworkTypeEnum.PUBLIC);
// 更新网络类型配置
updateNetworkTypeConfig(NetworkTypeEnum.PUBLIC);
} catch (Exception e) {
log.error("切换到公网失败: {}", e.getMessage());
}
}
/**
* 启动配置监控
*/
private void startConfigMonitoring() {
// 定期检查配置更新
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(this::checkConfigUpdates, 0, 60, TimeUnit.SECONDS);
}
/**
* 检查配置更新
*/
private void checkConfigUpdates() {
try {
// 检查是否有新的配置更新
List<ConfigUpdateMessage> updates = getPendingConfigUpdates();
for (ConfigUpdateMessage update : updates) {
handleConfigUpdate(update);
}
} catch (Exception e) {
log.error("检查配置更新失败: {}", e.getMessage());
}
}
// 其他辅助方法...
private MqttServerInfo getLatestMqttConfig() {
// 从配置服务获取最新MQTT配置
return configApiService.getMqttServerConfig();
}
private boolean validateMqttConfig(MqttServerInfo config) {
// MQTT配置验证逻辑
return config != null &&
StringUtils.isNotBlank(config.getHost()) &&
config.getPort() > 0 &&
StringUtils.isNotBlank(config.getUsername());
}
private boolean testMqttConnection(MqttServerInfo config) {
// 测试MQTT连接
try {
// 创建临时客户端测试连接
MqttClient testClient = MqttClient.builder()
.identifier("test-client")
.serverHost(config.getHost())
.serverPort(config.getPort())
.buildBlocking();
testClient.connectWith()
.simpleAuth()
.username(config.getUsername())
.password(config.getPassword().getBytes())
.applySimpleAuth()
.send();
boolean connected = testClient.getState() == MqttClientState.CONNECTED;
// 断开测试连接
testClient.disconnect();
return connected;
} catch (Exception e) {
log.error("MQTT连接测试失败: {}", e.getMessage());
return false;
}
}
private void applyMqttConfig(MqttServerInfo newConfig) {
// 应用新的MQTT配置
mqttClient.initialClient(newConfig);
// 更新本地配置缓存
currentConfig.put("mqtt.server", newConfig);
}
}
场景3: 高可用消息处理
高可用消息处理架构
完整实现代码
@Component
public class HighAvailabilityMessageProcessor {
@Autowired
private HiveMqMqttClient mqttClient;
private final Map<String, MessageHandler> messageHandlers = new ConcurrentHashMap<>();
private final Map<String, Consumer<ConsumerMessage>> messageProcessors = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
// 注册消息处理器
registerMessageHandlers();
// 注册消息监听器
registerMessageListeners();
}
/**
* 注册消息处理器
*/
private void registerMessageHandlers() {
// 告警消息处理器
messageHandlers.put("alert", new AlertMessageHandler());
// 指标消息处理器
messageHandlers.put("metric", new MetricMessageHandler());
// 事件消息处理器
messageHandlers.put("event", new EventMessageHandler());
// 系统消息处理器
messageHandlers.put("system", new SystemMessageHandler());
}
/**
* 注册消息监听器
*/
private void registerMessageListeners() {
// 告警消息监听器
mqttClient.registerConsumer("/alerts/+", this::handleAlertMessage);
// 指标消息监听器
mqttClient.registerConsumer("/metrics/+", this::handleMetricMessage);
// 事件消息监听器
mqttClient.registerConsumer("/events/+", this::handleEventMessage);
// 系统消息监听器
mqttClient.registerConsumer("/system/+", this::handleSystemMessage);
}
/**
* 处理告警消息
*/
private void handleAlertMessage(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析告警消息
AlertMessage alert = JsonUtils.fromJson(payload, AlertMessage.class);
// 获取告警处理器
MessageHandler handler = messageHandlers.get("alert");
if (handler != null) {
// 处理告警消息
handler.handle(message);
log.info("告警消息已处理 - 主题: {}, 告警级别: {}",
topic, alert.getSeverity());
} else {
log.warn("未找到告警消息处理器");
}
} catch (Exception e) {
log.error("处理告警消息失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 处理指标消息
*/
private void handleMetricMessage(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析指标消息
MetricMessage metric = JsonUtils.fromJson(payload, MetricMessage.class);
// 获取指标处理器
MessageHandler handler = messageHandlers.get("metric");
if (handler != null) {
// 处理指标消息
handler.handle(message);
log.info("指标消息已处理 - 主题: {}, 指标类型: {}",
topic, metric.getMetricType());
} else {
log.warn("未找到指标消息处理器");
}
} catch (Exception e) {
log.error("处理指标消息失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 处理事件消息
*/
private void handleEventMessage(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析事件消息
EventMessage event = JsonUtils.fromJson(payload, EventMessage.class);
// 获取事件处理器
MessageHandler handler = messageHandlers.get("event");
if (handler != null) {
// 处理事件消息
handler.handle(message);
log.info("事件消息已处理 - 主题: {}, 事件类型: {}",
topic, event.getEventType());
} else {
log.warn("未找到事件消息处理器");
}
} catch (Exception e) {
log.error("处理事件消息失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
/**
* 处理系统消息
*/
private void handleSystemMessage(ConsumerMessage message) {
try {
String topic = message.getTopic();
String payload = new String(message.getPayload());
// 解析系统消息
SystemMessage system = JsonUtils.fromJson(payload, SystemMessage.class);
// 获取系统处理器
MessageHandler handler = messageHandlers.get("system");
if (handler != null) {
// 处理系统消息
handler.handle(message);
log.info("系统消息已处理 - 主题: {}, 系统操作: {}",
topic, system.getOperation());
} else {
log.warn("未找到系统消息处理器");
}
} catch (Exception e) {
log.error("处理系统消息失败 - 主题: {}, 错误: {}", message.getTopic(), e.getMessage());
}
}
}
场景4: 故障恢复处理
故障恢复机制
完整实现代码
@Component
public class FaultRecoveryService {
@Autowired
private HiveMqMqttClient mqttClient;
private final Map<String, Consumer<ConsumerMessage>> listenerCache = new ConcurrentHashMap<>();
private final AtomicBoolean recoveryInProgress = new AtomicBoolean(false);
private final AtomicInteger recoveryAttempts = new AtomicInteger(0);
private static final int MAX_RECOVERY_ATTEMPTS = 5;
private static final long RECOVERY_RETRY_DELAY = 30; // 30秒
@PostConstruct
public void init() {
// 订阅故障事件
subscribeToFaultEvents();
// 启动健康检查
startHealthCheck();
}
/**
* 订阅故障事件
*/
private void subscribeToFaultEvents() {
// 连接故障事件
MqttEventBus.connectionStateFlow
.filter(event -> event.getState() == ConnectionState.ABNORMAL_DISCONNECT)
.subscribe(this::handleConnectionFailure);
// 会话过期事件
MqttEventBus.connectionStateFlow
.filter(event -> event.getState() == ConnectionState.SESSION_EXPIRED)
.subscribe(this::handleSessionExpired);
// 网络质量事件
MqttEventBus.networkQualityFlow
.filter(event -> event.getStats().getPacketLossRate() > 0.2)
.subscribe(this::handleNetworkFailure);
}
/**
* 处理连接故障
*/
private void handleConnectionFailure(ConnectionStateEvent event) {
log.warn("检测到连接故障,开始故障恢复流程 - 原因: {}", event.getReason());
if (recoveryInProgress.compareAndSet(false, true)) {
startConnectionRecovery();
}
}
/**
* 处理会话过期
*/
private void handleSessionExpired(ConnectionStateEvent event) {
log.warn("检测到会话过期,开始会话恢复流程");
if (recoveryInProgress.compareAndSet(false, true)) {
startSessionRecovery();
}
}
/**
* 处理网络故障
*/
private void handleNetworkFailure(NetworkQualityEvent event) {
log.warn("检测到网络故障,丢包率: {}%",
event.getStats().getPacketLossRate() * 100);
if (recoveryInProgress.compareAndSet(false, true)) {
startNetworkRecovery();
}
}
/**
* 启动连接恢复
*/
private void startConnectionRecovery() {
try {
log.info("开始连接故障恢复流程");
// 重置重连计数器
recoveryAttempts.set(0);
// 执行连接恢复
performConnectionRecovery();
} catch (Exception e) {
log.error("连接故障恢复失败: {}", e.getMessage());
scheduleRecoveryRetry();
}
}
/**
* 启动会话恢复
*/
private void startSessionRecovery() {
try {
log.info("开始会话恢复流程");
// 重新初始化客户端
mqttClient.reinitialize();
// 重新注册监听器
reRegisterAllListeners();
log.info("会话恢复流程已完成");
} catch (Exception e) {
log.error("会话恢复失败: {}", e.getMessage());
scheduleRecoveryRetry();
} finally {
recoveryInProgress.set(false);
}
}
/**
* 启动网络恢复
*/
private void startNetworkRecovery() {
try {
log.info("开始网络故障恢复流程");
// 尝试网络切换
performNetworkSwitch();
// 重新建立连接
mqttClient.reinitialize();
log.info("网络故障恢复流程已完成");
} catch (Exception e) {
log.error("网络故障恢复失败: {}", e.getMessage());
scheduleRecoveryRetry();
} finally {
recoveryInProgress.set(false);
}
}
/**
* 执行连接恢复
*/
private void performConnectionRecovery() {
try {
// 检查重连次数
if (recoveryAttempts.get() >= MAX_RECOVERY_ATTEMPTS) {
log.error("连接恢复重试次数已达上限,停止恢复");
recoveryInProgress.set(false);
return;
}
// 增加重连次数
recoveryAttempts.incrementAndGet();
log.info("执行连接恢复,第{}次尝试", recoveryAttempts.get());
// 重新初始化客户端
mqttClient.reinitialize();
// 重新注册监听器
reRegisterAllListeners();
// 验证恢复结果
if (validateRecovery()) {
log.info("连接恢复成功");
recoveryInProgress.set(false);
recoveryAttempts.set(0);
} else {
log.warn("连接恢复验证失败,将重试");
scheduleRecoveryRetry();
}
} catch (Exception e) {
log.error("执行连接恢复失败: {}", e.getMessage());
scheduleRecoveryRetry();
}
}
/**
* 执行网络切换
*/
private void performNetworkSwitch() {
try {
// 获取当前网络类型
NetworkTypeEnum currentNetwork = getCurrentNetworkType();
if (currentNetwork == NetworkTypeEnum.PUBLIC) {
// 切换到VPC网络
mqttClient.changeServer(NetworkTypeEnum.VPC);
log.info("已切换到VPC网络");
} else {
// 切换到公网
mqttClient.changeServer(NetworkTypeEnum.PUBLIC);
log.info("已切换到公网");
}
} catch (Exception e) {
log.error("网络切换失败: {}", e.getMessage());
}
}
/**
* 重新注册所有监听器
*/
private void reRegisterAllListeners() {
try {
// 重新注册所有缓存的监听器
for (Map.Entry<String, Consumer<ConsumerMessage>> entry : listenerCache.entrySet()) {
mqttClient.registerConsumer(entry.getKey(), entry.getValue());
}
log.info("所有监听器已重新注册,共{}个", listenerCache.size());
} catch (Exception e) {
log.error("重新注册监听器失败: {}", e.getMessage());
}
}
/**
* 验证恢复结果
*/
private boolean validateRecovery() {
try {
// 检查连接状态
boolean connected = mqttClient.isConnected();
// 检查网络质量
NetworkQualityStats stats = getCurrentNetworkQuality();
boolean networkOk = stats.getAverageLatency() < 500 && stats.getPacketLossRate() < 0.1;
return connected && networkOk;
} catch (Exception e) {
log.error("验证恢复结果失败: {}", e.getMessage());
return false;
}
}
/**
* 调度恢复重试
*/
private void scheduleRecoveryRetry() {
try {
log.info("调度恢复重试,延迟{}秒", RECOVERY_RETRY_DELAY);
// 延迟重试
CompletableFuture.delayedExecutor(RECOVERY_RETRY_DELAY, TimeUnit.SECONDS)
.execute(() -> {
if (recoveryInProgress.get()) {
performConnectionRecovery();
}
});
} catch (Exception e) {
log.error("调度恢复重试失败: {}", e.getMessage());
recoveryInProgress.set(false);
}
}
/**
* 启动健康检查
*/
private void startHealthCheck() {
// 定期健康检查
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(this::performHealthCheck, 0, 60, TimeUnit.SECONDS);
}
/**
* 执行健康检查
*/
private void performHealthCheck() {
try {
// 检查连接状态
if (!mqttClient.isConnected()) {
log.warn("健康检查发现连接断开");
if (recoveryInProgress.compareAndSet(false, true)) {
startConnectionRecovery();
}
}
// 检查网络质量
NetworkQualityStats stats = getCurrentNetworkQuality();
if (stats.getAverageLatency() > 1000 || stats.getPacketLossRate() > 0.3) {
log.warn("健康检查发现网络质量下降");
if (recoveryInProgress.compareAndSet(false, true)) {
startNetworkRecovery();
}
}
} catch (Exception e) {
log.error("执行健康检查失败: {}", e.getMessage());
}
}
/**
* 缓存监听器
*/
public void cacheListener(String topic, Consumer<ConsumerMessage> callback) {
listenerCache.put(topic, callback);
log.debug("监听器已缓存 - 主题: {}", topic);
}
/**
* 移除缓存的监听器
*/
public void removeCachedListener(String topic) {
listenerCache.remove(topic);
log.debug("缓存的监听器已移除 - 主题: {}", topic);
}
/**
* 获取恢复状态
*/
public boolean isRecoveryInProgress() {
return recoveryInProgress.get();
}
/**
* 获取恢复尝试次数
*/
public int getRecoveryAttempts() {
return recoveryAttempts.get();
}
// 辅助方法
private NetworkTypeEnum getCurrentNetworkType() {
// 获取当前网络类型
return NetworkTypeEnum.PUBLIC; // 默认值
}
private NetworkQualityStats getCurrentNetworkQuality() {
// 获取当前网络质量统计
return new NetworkQualityStats(); // 默认值
}
}