收藏
0
1
分享
举报
·3 小时前发布·90次阅读

接口超时后别急着重试:给小产品补上任务身份

独立开发商业增长付费用户

设想一个图片导出工具:用户点了“生成”,等了十几秒,页面提示超时。他再点一次,后台却出现两个任务。这是用于讨论的假设场景,不是线上事故复盘。

问题出在一个容易被界面掩盖的差别:页面没拿到结果,不代表后台没做事。AWS 的《Timeouts, retries, and backoff with jitter》明确提醒,超时或失败不能证明副作用尚未发生;重试还可能加重已经过载的服务。[1]

对于小产品,我建议先把“这次操作是谁”说清楚,再决定自动重试几次。下面是一份可以拿去讨论实现的设计草案,未经过特定项目的生产验证。

一、一个任务身份,多次传输尝试

把用户的一次生成意图记为 operation_id。第一次提交前生成它,网络断开后的重试继续携带同一个值。用户明确修改参数、重新发起一次生成,才创建新的 operation_id。

另外给每一次网络请求分配 attempt_id,便于排查。不要拿它做去重依据:第一次传输和第二次传输的编号本来就应该不同。

例如,同一次“导出本周菜单”可以有两条请求日志,但只关联一条导出任务。日志至少记录任务身份、传输次数、请求开始时间、结果状态和错误类别;具体菜单正文没有必要为了排错全部写进日志。

二、服务端要认得这次任务

只在前端禁用按钮并不够,刷新页面、网络重发或另一个客户端仍可能提交。建议在服务端按“账号+操作类型+operation_id”建立唯一约束,并保存本次参数的稳定摘要。同一个身份带着不同参数来,返回明确冲突,不能悄悄覆盖。

这里的关键是原子性。不能先查数据库“没有这个任务”,再毫无保护地插入;两个并发请求可能都查到没有。在同一个数据库事务里创建任务记录和待处理记录,靠唯一约束决定谁真正创建成功,重复请求则读取原任务。参数摘要还要固定字段顺序、默认值等规范,避免相同意思被算成不同请求。

这只解决本地任务的重复创建。工作进程可能在调用外部生成服务成功后、写回结果前崩溃。如果外部服务既不支持幂等键,也不能按任务编号查询,就仍然存在结果不确定的窗口。此时应进入“待核对”状态,不能宣称本地加一张表就实现了整条链路只执行一次。

三、别把“结果未知”显示成“请重新创建”

我会为这个假设工具设计四类可见状态:已接收、处理中、已完成、需要核对。只有能够确定的失败才展示失败原因。

提交超时后可以显示:“暂时没有收到确认,正在查询这次任务。”随后按任务身份查询状态,查询接口也必须校验账号权限。用户重新打开页面时,尽量恢复同一任务,而不是自动生成新身份再提交。

这里还有一个细节:查询暂时返回“找不到”,也未必足以证明首次请求永远不会成功。原请求可能仍在传输或等待处理。所以后续重提仍需沿用原身份,让服务端解决竞争,而不是根据一次空查询创建新身份。

四、先确定可以重试,再安排等待

对于允许重试的临时故障,设置总等待预算与尝试上限,等待中加入随机分散。检查 SDK 是否已经重试,避免外层再套一层把请求数量放大。这些是 AWS 原文讨论的工程原则;具体等待时间要结合你的服务延迟与用户能接受的等待来定,不能照抄一个万能数字。[1]

幂等键的保障也有范围。Stripe 的当前文档就明确区分 API v1 与 v2;其中 v1 的同键重试会返回已保存的响应,包括部分错误结果,而且键被清理后再次使用会被当成新请求。[2] 这里引用的是接口设计实例,不表示所有供应商都有同样行为。接入前要读清楚保留时间、参数冲突和失败响应规则。

五、上线前,故意制造这几种中断

下面是建议测试,不是已经跑过的测试结果:

  1. 本地任务已创建,但客户端收不到响应。原身份重试后,数据库应仍只有一个任务,并能查回它。

  2. 两个相同身份、相同参数的请求同时到达。应关联同一任务,不能各自排队执行。

  3. 相同身份换了参数。应提示冲突,原任务内容不变。

  4. 外部服务已完成,本地工作进程在写回前退出。恢复后应查询或核对外部结果;不具备核对能力时,清楚暴露不确定状态。

  5. 用户刷新、关闭后重新进入。验证任务能否恢复,以及身份保存多久、过期后如何说明,不能只测试当前页面内的按钮。

验收时同时看三件事:用户看到的状态、数据库里的任务数量、外部服务实际执行次数。只看页面最终显示成功,可能漏掉后台做了两遍。

如果今天只能改一个地方,我建议从“提交超时”这条路径开始:保留任务身份,提供查询入口,区分明确失败与结果未知。再用上面第一种中断验证它。做到这里,重试按钮才有一个可靠的落点。

参考资料

[1] Marc Brooker,Timeouts, retries, and backoff with jitter,AWS,2019-12-05。https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/

[2] Stripe API Reference,Idempotent requests,查阅于2026-11-04。https://docs.stripe.com/api/idempotent_requests

本文的图片导出、菜单导出场景和测试清单为围绕上述原则整理的设计建议,不代表 AWS 或 Stripe 对该方案的验证。

讨论 (1)

0/250

    关于作者

    心得体会

    TA 还没有留下个人简介

    Solo 独立开发者社区support@solo.xin
    关于社区成长规则SOLO.cc隐私政策用户协议商务合作友情链接订阅更新(RSS)投稿赞助

    © 2023 SOLO · 为独立开发者而生