把 QoS 设置为较高级别,也不能直接宣称下游业务永远不会重复处理。
本文使用MQTT 3.1.1、HTTP 或 CoAP 的演示设备与消息。设备通信需要同时定义身份、数据语义、时序与失败处理。协议传输确认不自动代表业务动作完成,采样时间也不能简单用服务器收到消息的时刻替代。
1. 从现象推到机制
QoS 约定参与协议交付的可靠性阶段,端到端业务还包含发布端重建消息、代理转发和消费事务。一次开门或记账动作需要业务唯一身份,消费者重启后也要能识别已经处理的事件。
图中的四个节点分别表示协议交付、业务身份、消费事务、恢复处理。顺着实线检查输入如何变成输出,再沿虚线核对反馈条件。图示表达的是本文讨论的关系,不是实测曲线或现场截图。
2. 最小实现与输入条件
用无副作用的计数演示重复消息,接收端同时记录协议消息与业务事件号。业务去重状态要有明确保留期限。
1
2
3
4
event_id = stable business event identity
receive message
if event_id already processed: return stored result
else: apply business change and record event atomically
在独立代理与虚构设备标识下实验,保留发布端、代理和消费端记录。命令与遥测使用不同主题及权限;网络断开、重复消息和设备重启都要作为正常分支观察。
3. 用对照区分原因
下表列出需要主动改变的条件。预期行为来自机制分析,复现时还需记录运行环境和原始输出,不能将预期当作已经测得的结果。
| 改变的条件 | 需要验证的行为 |
|---|---|
| 相同业务消息重新发布 | 新协议过程仍可能对应旧业务 |
| 消费后确认前进程退出 | 恢复时可能再次收到消息 |
| 消费者有持久去重记录 | 重复消息不应重复产生业务结果 |
对照 1:相同业务消息重新发布
新协议过程仍可能对应旧业务。观察时记录业务事件号而非仅报文编号。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
对照 2:消费后确认前进程退出
恢复时可能再次收到消息。观察时记录提交点与协议确认顺序。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
对照 3:消费者有持久去重记录
重复消息不应重复产生业务结果。观察时记录唯一约束和已有处理状态。把这个条件与基准情形分开,有助于判断变化来自哪一层;若得到相反结果,应先核对前提,再修改实现。
4. 适用条件与取舍
去重不能静默丢弃同号不同内容。事件号复用时应核对摘要或关键字段,避免把错误数据当成合法重传。
一次正常运行只覆盖了这组输入。继续扩展前,应把上面的异常对照保留下来,尤其关注“消费者有持久去重记录”这一分支。后续方案若改变了图中任意一处依赖,原来的判断就要重新验证,不能仅凭界面相似或返回值相同沿用结论。