本文是《MCP实战手记系列(十):MCP Server高可用实战》的延伸知识点。
配超时是件特别容易干错的事:每处看着都合理,凑一起就打架。我见过最典型的三个疑问——“熔断为什么有时候不触发”、“优雅停机为什么没用”、“下游都恢复了我这边怎么还在报错”——根因基本都在超时配错了,不是熔断或停机的锅。
层级关系
请求总超时(Servlet / 网关层) ├── 工具调用超时 │ ├── HTTP连接超时 │ ├── HTTP读取超时 │ └── HTTP写入超时 └── 数据库查询超时 ├── 连接获取超时 └── 查询超时五条约束
| 原则 | 违反了会怎样 |
|---|---|
| 请求总超时 > 各下游超时之和 | 下游还没返回,上层先断了,客户端只拿到一个说不清的超时 |
| 越往下层,超时越短 | 下游卡住时上游还在等,线程白白占着 |
| 慢调用阈值 < 工具超时 | 阈值比超时还长,就永远只能统计到"抛异常",慢调用等于没统计 |
| 优雅停机等待 > 最长工具超时 | 等待时间一到就强杀,优雅停机形同虚设 |
| 超时必须配重试策略 | 不重试体验差,重试太猛又会把刚缓过来的下游重新打挂 |
第三条值得单独说。Resilience4j默认只有抛异常才算失败,慢调用不算。所以要把slowCallDurationThreshold配进来,把慢调用计进来——但如果这个阈值设得比接口超时还长,请求早就超时抛异常了,慢调用永远统计不到,熔断就只在"下游彻底挂了"的时候才开,对下游变慢完全没反应。而下游变慢恰恰是更常见的故障形态。
一个自相矛盾的例子
我们自己的配置里就有过这么一处:优雅停机等待30秒,设备接口超时也是30秒。按第四条,等待时间必须大于最长工具超时——30秒等于30秒,真有请求卡满30秒时,停机等待同时到期,照样强杀。
修法二选一:把接口超时压下去(比如10秒),或者把停机等待加到45秒。我选了前者——30秒的接口超时本来就该压,它已经把Tomcat线程占得太久了。
重试那条
顺便把重试说清楚,因为它跟超时是绑在一起的:
- 只对幂等的读操作重试。写操作要么先做幂等键,要么别重试,否则一个请求被执行两次。
- 指数退避 + 抖动。固定间隔重试会让所有客户端在同一时刻重试,形成重试风暴。
- 限制最大次数。下游正在恢复的时候,无上限的重试能把它重新摁倒。
小结
配超时之前先把层级画出来,然后按这五条从上到下核一遍。核完你会发现,很多"玄学问题"其实是两个超时数字撞了。
同专题推荐
本文是「MCP Server高可用」小专题的第3篇,共5篇:
- Nginx开源版没有主动探活:四种补救方案和一个能用的脚本
- 发版就掉请求?Spring Boot优雅停机的四步
- 超时不是一个数字,是一套体系:MCP Server的五条约束(← 当前这篇)
- 高可用配完之后:该看哪几个指标,池子该设多大(链接待补)
- 缓存穿透、击穿、雪崩:三个概念,三种解法(链接待补)
相关阅读
- 《MCP实战手记系列(十):MCP Server高可用实战》(本文延伸自该篇)
- 《MCP实战手记系列(九):生产化MCP Server的6层安全防护》
- 配套代码:https://gitee.com/ethanliang2016/mcp-in-action(tag
v10)