1.HTTP 接口重试:超时后能再提交一次吗?
wabicai
# 1.HTTP 接口重试:超时后能再提交一次吗?
用户点了“下单”,前端等到超时,但服务端可能已经创建订单。此时直接再发一次 POST,有机会多建一笔。这就是做接口时要考虑幂等的原因。
# 先分清 HTTP 方法的语义
按 HTTP 规范,GET 是读取;PUT、DELETE 的预期效果是幂等的:相同请求执行一次或多次,目标资源的最终效果相同。POST 不自带这个保证,创建订单、发起支付尤其要小心。
这里说的是业务效果,不是“每次响应字节完全一样”。服务端记录两条访问日志,也不影响该方法的幂等语义。
# POST /orders 怎么防重复?
客户端为一次下单意图生成一个幂等键,重试时仍带同一个键。服务端在同一用户或业务主体范围内保存这个键、请求内容摘要和处理结果:
- 首次请求通过唯一约束取得处理权,再创建订单。
- 同一键、同一请求内容再次到来时,返回已保存的结果,而不是再建一笔订单。
- 同一键却换了请求内容时,拒绝复用并说明冲突。
- 并发请求、处理中失败、结果保存失败及键的过期时间都需要明确定义。
不能只写“先查有没有,再创建”:两个请求可能同时查到不存在。需要数据库唯一约束或事务来兜住并发;如果还调用支付服务,本地去重也代替不了支付侧的幂等处理。
# 接口还要约定什么?
成功创建资源可以返回 201 Created。输入错误、业务冲突和服务端故障要给出可区分的状态码与错误信息。日志里保留请求标识、耗时和失败的下游,不要把密钥或完整敏感数据打进去。
最后用几种情况验证:首次提交、原样重试、同键不同内容、两次并发提交,以及处理到一半失败后再试。只测“正常提交一次”发现不了重复下单问题。