54 lines
2.2 KiB
Markdown
54 lines
2.2 KiB
Markdown
# MQTT 待确认命令启动清理与重试间隔设计
|
|
|
|
## 背景
|
|
|
|
MQTT 待 ACK 命令保存在 Redis 中,默认保留 24 小时。应用重启后,旧命令的
|
|
`nextRetryAt` 通常已经早于当前时间,因此重试扫描任务启动后会立即重新下发旧命令。
|
|
|
|
当前服务按单实例部署处理。目标是启动时清除旧待确认命令,并将新命令等待 ACK 的
|
|
时间从 30 秒调整为 10 秒。
|
|
|
|
## 行为约定
|
|
|
|
- 应用每次启动完成后清理全部 pending 命令。
|
|
- 清理范围包括 pending ID 集合及集合中每个命令对应的缓存对象。
|
|
- 不清理已经收到的 ACK 历史缓存。
|
|
- 启动清理失败只记录完整异常,不阻止应用启动。
|
|
- 新命令首次下发后等待 10 秒才具备重试条件。
|
|
- 重试扫描周期保持 5 秒,因此实际重发时间约为下发后的 10 至 15 秒。
|
|
- 最大重试次数保持 3 次,不包含首次发送。
|
|
|
|
## 设计
|
|
|
|
### 清理服务
|
|
|
|
在 `MqttCommandAckService` 增加公开的启动清理方法。方法读取 pending ID 集合,逐一
|
|
删除 `mqtt:command:pending:{commandId}`,然后清空 pending ID 集合,并返回清理数量。
|
|
清理操作应可重复执行,空集合返回 0。
|
|
|
|
### 启动时机
|
|
|
|
新增 MQTT 启动清理监听器,在 `ApplicationReadyEvent` 到达后执行一次。此时 Spring、
|
|
Redis 和 MQTT 相关 Bean 已完成初始化。监听器捕获运行时异常并记录完整异常栈,避免
|
|
Redis 短暂不可用导致整个应用启动失败。
|
|
|
|
### 重试配置
|
|
|
|
将 `mqtt.command-ack.retry-interval-ms` 设置为 `10000`。首次发送和每次重试后均继续使用
|
|
该配置计算 `nextRetryAt`。`scan-interval-ms` 保持 `5000`。
|
|
|
|
## 测试
|
|
|
|
- 清理方法删除集合中每个 pending 缓存并清空集合。
|
|
- 空 pending 集合清理成功且返回 0。
|
|
- 启动监听器在应用就绪事件后调用一次清理方法。
|
|
- 清理异常不会从监听器继续抛出。
|
|
- 配置绑定后的重试间隔为 10000 毫秒。
|
|
- 保留现有命令发送和三次重试测试。
|
|
|
|
## 非目标
|
|
|
|
- 不修改 ACK 消息格式、MQTT Topic 或命令 Payload。
|
|
- 不清理 ACK 历史缓存。
|
|
- 不设计多实例命令归属;若后续改为多实例部署,需要重新设计启动清理策略。
|