超时预算别层层加码:把剩余时间传给下游
【摘要】 超时预算别层层加码:把剩余时间传给下游网关给一次请求留了 800 毫秒。订单服务自己又设了 800 毫秒,库存服务再设 800 毫秒。用户侧早就超时断开,下游还在空转,重试再叠一层,就把依赖打成重试风暴。超时不是每一跳都重新发一张整额支票,而是一张会变少的预算。 先约定三件事入口只发一次总预算,例如 800ms,并写进上下文,而不是只写在网关配置里。每一跳取 min(自己的上限, 剩余预算...
超时预算别层层加码:把剩余时间传给下游
网关给一次请求留了 800 毫秒。订单服务自己又设了 800 毫秒,库存服务再设 800 毫秒。用户侧早就超时断开,下游还在空转,重试再叠一层,就把依赖打成重试风暴。
超时不是每一跳都重新发一张整额支票,而是一张会变少的预算。
先约定三件事
- 入口只发一次总预算,例如 800ms,并写进上下文,而不是只写在网关配置里。
- 每一跳取 min(自己的上限, 剩余预算 - 预留)。预留留给序列化、队列等待和返回路径,常见是 20 到 50ms。
- 剩余预算小于预留时直接失败,不要再打下游。失败要带原因,方便入口决定是否对用户重试。
一个数字例子
入口预算 800ms。网关已用 30ms,剩余 770ms。订单服务上限 500ms,预留 40ms,实际截止时间是 now + min(500, 770-40) = 500ms。库存服务收到时剩余 180ms,自身上限 300ms,预留 40ms,于是只用 140ms。若剩余只剩 15ms,库存服务不再发起调用,返回 BUDGET_EXHAUSTED。
这样做的好处是:下游的慢调用不会超过用户还能等待的时间;入口的重试只会打在“还来得及”的请求上。
和熔断、限流怎么配合
- 熔断看的是错误率,不替代预算。预算耗尽应记为取消,不要记成下游 5xx,否则熔断会被自己的超时放大。
- 限流保护容量,预算保护时延。两者都要有,但计数口径分开。
- 重试只允许在剩余预算足够覆盖一次完整下游调用时发生,并且要换一个幂等键或沿用同一个,避免重复下单。
落地时容易踩的坑
- 只在日志里打印超时,没有把截止时间传给客户端。线程池里的任务拿不到父请求的剩余时间,预算就断了。
- 用固定 sleep 做退避,不看剩余预算。第二次重试发出去时,用户连接已经关了。
- 把时钟差当成预算。跨机器用单调时钟算本机耗时,截止时间用绝对时间并允许少量时钟偏移。
把“每一层都设一个看起来安全的大超时”改成“把剩余时间传下去”,慢依赖会在预算用完时自己停下来,而不是靠用户刷新把流量再放大一轮。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)