TT Lab
开始
学习 学习路径 课程

幂等性 — 点两次也只扣一次款

幂等请求也需要重试预算:设计原理

在 TT Lab 中继续学习

一句话总结

重试不是“再来一次”,而是在剩余的时间和次数内,重新发送安全的请求的一种策略。

为什么需要它

当客户端对一个很慢的服务同时发起重试时,请求会继续堆积在本已积压的队列里。 如果每个请求的 timeout 设为 5 秒、尝试 3 次,整个任务就无法在 5 秒内完成。 应该一开始就算出截止时间,并在每次调用和每次等待之前重新计算剩余时间。 即使有幂等键,成本、负载和用户等待时间也不会因此消失。

工作原理

send(남은 시간) → 응답 → 재시도할 상태인가? → 재생해도 안전한가?
                                                ↓
종료 ← 횟수 또는 전체 예산 소진 ← 지터 + Retry-After 대기 계산
                                                ↓
                                            sleep → 다음 호출

这个实验的策略只重试 429、502、503、504。GET、HEAD、PUT、DELETE 以该 API 的 幂等契约为前提允许重试,POST 只有在带有非空键时才允许。如果服务器并没有真正以原子方式 处理这个键,那么仅仅在客户端附上一个字符串并不安全。 前面的幂等性实验讲的正是服务器端的这个前提。

在现场相遇的样子

对指数退避加上抖动,可以减少所有客户端在同一时刻醒来的现象。 如果服务器的 Retry-After 比本地等待时间更长,就采用更长的值。如果服务器要求的 等待时间超过整个预算,不会擅自缩短它并提前重试,而是直接返回当前响应。这里明确了一个限制: 只支持整数秒格式,不支持 HTTP 日期格式。

下一项实验要做什么

用模拟的单调时钟、sleep 和 send,在不真正等待的情况下验证全部 8 个步骤。前提是 send 是一个 在收到的剩余时间之内就会返回响应的适配器。同步函数如果永远阻塞,执行器无法强制中断它, 所以真实的 HTTP 适配器还需要单独设置 timeout。预算和最大次数都包含第一次尝试。 不要对所有状态码都重试,也不要把 412 冲突当作网络故障处理。

参考:HTTP 幂等方法