问问助手

五个服务串起来,超时该谁定

2026-10-28 Aryee 1
五个服务串起来,超时该谁定

一、一次点击,到底该等多久

点一下提交订单,页面转圈,第三十秒弹出一个失败。

用户看到的是一个失败,系统里发生的是另一件事:五层服务各自在等,各自在算,谁也不知道上面已经放弃了。

二、每层都设了超时,为什么还会等这么久

大多数系统里,每一层确实都配了超时。

页面等三十秒,接入层等二十秒,业务服务等十秒,它调的下游等五秒,数据库查询等三秒。

看起来一层比一层严格,很合理。问题在于这几个数之间没有任何关系,是五个人分别拍的。

三、层与层之间,缺的是同一个数

第一种情况是上面已经放弃,下面还在算。

接入层在第二十秒返回了失败,业务服务还在等那个五秒的下游,下游还在查数据库。用户刷新重来,这套动作又跑一遍。

第二种情况是每层还带着重试。这件事比第一件更贵,下一节单独说。

四、时间预算应该由入口定

正确的关系不是每层各拍一个数,而是入口给一个总预算,往下传剩余时间。

举个例子。这次请求总共给三秒。业务服务自己排队和计算花了半秒,那么传给下游的预算只剩两秒半。

下游拿到的是两秒半,不是它自己那个固定值。它再用掉一部分,剩下多少继续往下传。

五、单次超时必须小于剩余预算

有一个很简单的乘法要算:单次超时乘以(一加重试次数),必须小于本层的可用时间。

上游给三秒,本层预留半秒,可用就是两秒半。单次超时一点二秒、重试一次,最坏占两秒四,刚好在预算里。

如果单次超时一秒、重试两次,最坏就是三秒,已经顶穿上游。这时上游早就返回了失败,本层还在空转。

六、一次重试,为什么能变成二十七次请求

假设三层都在重试。

最上面发一次,第二层失败后重试三次,第三层再对数据库重试三次。数据库看到的是三次乘三次再乘一,二十七个请求。

这不是理论值。入口只来了一次用户请求,底层被打了二十七次,而那个用户第三十秒已经看到失败了。

七、重试预算:给重试本身也设一个上限

业界一个常用的做法是给重试流量单独设上限:重试的请求量不超过正常请求的两成。

超过就当场返回失败,不再试。

这样做的好处是,下游已经很吃力的时候,不会因为上游集体重试被彻底压垮。失败得早一点,恢复得快一点。

八、重试该放在哪一层

只有入口那一层重试,中间层把错误原样往上传。

理由就是上一节那个乘法。每多一层重试,底下的请求量就再乘一次。

跨团队的时候这条最难落地,因为每一层的人都觉得自己加一次重试是在做好事。

九、写操作为什么不该重试

读请求失败重发一次,最多是浪费一次查询。

写请求不一样。你重发的那次可能已经被执行过了,只是回话丢了。再发一次,就多下了一单,或者多扣了一笔钱。

判断的依据是这件事重放两次会不会和一次不同。会不同,就不要自动重试。

十、退避和抖动解决的是什么

下游已经忙不过来的时候,立刻重发等于再压一下。

所以要等一会再试,而且等的时间要逐次变长。这是退避。

还要加一点随机。所有客户端一起失败,一起等一秒,又一起醒来,等于没有等。把等待时间打散,叫抖动。

上游如果直接告诉你隔多久再来,就取它给的时间和你算的时间里面较大的那个,别拿自己的覆盖它。

十一、数据库那三层超时

数据库这一端通常有三层时间要一起看:业务的总超时、等连接池空位的时间、单条语句的执行时间。

约束只有一条:里面几层加起来不能超过外面那一层。

等连接池的时间占业务总超时的两三成,是个常见起点。这个等待如果经常接近上限,说明要么池子小了,要么有人拿着连接不还。

十二、超时不是越短越好

把超时压得很短,看起来是让系统更快放弃,实际上会把正常但稍慢的请求判成失败。

失败会触发重试,重试又加重下游,原本只是慢,最后变成错。

该看的是这条操作在正常日子里最慢的那一档要多久,再往前留一点余量。看平均值会低估,因为故障总是从慢的那一端开始。

十三、八月那场七个多小时的故障

2026 年 8 月 17 日,GitHub 发生了一次持续 7 小时 47 分钟的大故障。

公开复盘里,起因写在容量这一侧,而放大它的是重试:大量请求在失败后不断重发,把已经吃紧的系统压得更死。

事后他们落了两项:服务之间的重试上限、重试预算和可变超时统一起来;把平时不响的低优先级告警重新审一遍。

这两件事都不新,难的是全公司用同一套。

十四、今天就能做的四件事

第一,在入口记一个总预算,调用下游时把剩余时间带上,不让它用自己那个固定值。

第二,数一遍这条路径上到底有几处重试。相乘超过两处,先收掉中间层的。

第三,把写接口的自动重试关掉,只留人工或者入口那一层带幂等判断的重发。

第四,每个月看一次超时率和重试量,别只看平均值。这两个数一涨,说明有人正在替下游兜住问题。

十五、给管理层的那一页

要问三个问题,都能当场答出来才算过。

一是这次请求最坏要等多久,从点下去到看到结果,上限是多少。

二是最坏那一秒,底层会收到几倍于正常量的请求。

三是明天发现某个数不对,谁能不改代码把它调回来,多久生效。

你手上那套系统,卡在哪一步?

留个手机号和方便的时间,我打过来先听你说现状和限制,再给一个能执行的判断:这套系统该继续修、该动哪里,还是重做一版更省。

约一次沟通不接纯 UI 外包,只做系统层面的问题。不方便留号码,也可以直接跟助手说一句话。