任务长期处于 uploading,不能只看累计次数判断卡住。应检查领取、超时、租约与失败后的下一次时间。
持久队列把发送意图与网络执行分开。领取需并发约束,租约支持崩溃回收;回执丢失后的重试仍需业务幂等身份。
一、问题的范围与前提
消息传输、业务处理与设备执行具有不同完成条件。消息系统可以提供队列和协议确认,但不会自动把数据库写入与物理动作合成一个事务。事件身份、对象版本与会话范围需要由应用定义,尤其在重复、乱序和断网补传时。
二、技术分析与方案取舍
租约让 worker 崩溃后的任务有机会回收,但上传实际上仍可能被远端受理。回收以后先查稳定业务键的结果,比立即发第二次更安全。长耗时文件可以和关键注册任务分开调度,并观察最老等待时间。成功回执保存以后再处理文件清理,索引、业务状态与附件保留周期不能混成一步。
先区分状态、事件和命令,再选择传输语义与保留方式。发送端持久保存重要意图,接收端用稳定业务键管理去重与结果。队列领取与回收需要并发约束,超时与退避有整体预算,避免持续失败把下游压力无限放大。
三、实现与排查的顺序
- 原子领取到期任务。
- 设置上传超时租约。
- 失败退避回队。
- 确认回执后清理。
按这个顺序保留中间结果,可以区分输入条件、处理过程和最终输出。前一阶段的条件不成立时,先解释对应错误,再继续后面的试验;单次返回成功不足以覆盖整条链路。
最小示例
1
2
3
pending → claimed → sending → confirmed
失败:sending → pending,保存下次重试条件
中断:租约到期 → 查询结果 → 安全回收
状态是通用结构,不对应现场数据库字段。任务领取需要原子边界,回执未知时优先查询,成功后的业务记录与文件清理分别管理。
四、验证和结果解释
记录消息来源、序号、采集时间、接收时间和处理状态,有助于判断旧消息、重复消息与新事件。次数本身不能解释进展,应看一段时间内领取、失败、下一次执行和确认是否连贯。关键任务等待时间也比 worker 存活更能说明调度质量。
| 需要验证的结果 | 保留的对照 | 不能由此推出的结论 |
|---|---|---|
| 重启回收中断任务 | 固定输入与配置、对应输出 | 一次成功代表所有条件成功 |
| 重复不重复入库 | 中断前后状态与错误阶段 | 没有报错代表结果正确 |
| 慢任务不会饿死关键任务 | 恢复后的同条件复测 | 临时恢复代表根因已经消失 |
故障测试包括发送后断线、受理后丢回执、处理中崩溃和重连乱序。系统应能明确查询、回收或拒绝,不能把网络未知结果一律当作失败重发。保留消息不替代历史库,高 QoS 也不自动提供跨系统业务只执行一次。
五、适用边界与结论
next_retry_at 过去不一定异常,任务可能已执行。队列存活、任务进展与业务完成分别观察。
这条路径把“原子领取到期任务”与“确认回执后清理”连在一起,中间保留可复查的条件。实施时优先确认“重启回收中断任务”,再检查“慢任务不会饿死关键任务”;两者都满足,才能在当前样本与配置范围内评价方案。设备、数据或软件版本改变以后,相关假设需要重新验证。