Skip to main content

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.1MQTT 5.0优势说明
连接管理基础连接选项会话过期、连接原因码更精确的连接状态控制
消息传递QoS 0/1/2QoS 0/1/2 + 消息过期防止过期消息传递
主题订阅基础订阅主题别名、订阅选项减少网络传输开销
用户属性不支持支持用户属性更丰富的元数据传递
错误处理基础错误码详细错误码和原因字符串更精确的错误诊断
流量控制不支持接收最大值控制防止客户端过载
消息格式固定格式可变长度属性更灵活的消息结构

弱网环境对比​

场景MQTT 3.1.1MQTT 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.1MQTT 5.0提升幅度说明
连接恢复时间30-60秒1-3秒95%+网络恢复后快速重连
会话保持时间无会话保持2小时100%断网期间保持会话状态
消息传递可靠性QoS 0/1/2QoS 0/1/2 + 消息过期100%防止过期消息传递
网络切换时间重新连接连接复用90%+无需重新建立连接
错误诊断精度基础错误码详细错误码+原因字符串300%+更精确的故障定位
主题传输效率完整主题名主题别名60%+减少网络传输开销
流量控制能力无控制机制接收最大值控制100%防止客户端过载
消息格式灵活性固定格式可变长度属性200%+更灵活的消息结构

商用环境对比​

商用场景MQTT 3.1.1MQTT 5.0商用价值
长时间断网恢复需要重新连接和认证会话保持,快速恢复服务可用性提升95%
网络质量不稳定频繁断开重连智能重连+会话保持用户体验显著改善
大规模设备接入连接管理复杂流量控制+会话管理系统稳定性提升
消息可靠性要求可能丢失消息过期+QoS保证数据完整性保障
运维故障诊断错误信息有限详细错误码+原因故障定位效率提升80%
网络资源优化固定开销主题别名+流量控制带宽利用率提升60%

技术架构对比​

架构特性MQTT 3.1.1MQTT 5.0技术优势
协议扩展性有限扩展用户属性+可变格式更好的协议扩展能力
连接管理基础连接会话过期+原因码更精确的连接控制
消息传递基础QoSQoS+消息过期+优先级更丰富的消息传递机制
错误处理简单错误码详细错误码+原因字符串更完善的错误处理
流量控制无控制机制接收最大值+共享订阅更智能的流量管理
会话管理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(); // 默认值
}
}