3. 超时参数分类:连接超时、读取超时、写入超时、空闲超时
超时参数是连接池与熔断器之间的“触发扳机”。
很多团队把熔断搞成玄学,其实多半是超时设得乱七八糟。
我自己的经验是:理清这四类超时,熔断就稳了一半。
3.1 连接超时(Connect Timeout)
连接超时是客户端与服务端建立TCP连接时,愿意等待的最长时间。
说白了就是“握手阶段你让我等多久”。
典型值:
内网服务:500ms~1s
公网/跨机房:2~5s
我个人习惯把内网连接超时压到300ms,太长了说明网络有故障,早点失败比吊着强。
与熔断的关系:
连接超时触发时,请求还没开始传输数据,直接算一次失败。
如果下游服务间歇性TCP reset,连接超时很快刷满熔断窗口。
避坑: 我遇到过某团队把连接超时设成30s,结果服务挂了半小时才被熔断。原因是连接池满了,新请求排队等空闲连接,等来等去全超时了。
3.2 读取超时(Read Timeout / Socket Timeout)
连接建立之后,客户端等待服务端返回数据的最大时间。
其实是等待数据包到达的时间间隔——如果服务端处理慢或网络丢包,就会触发这个超时。
典型值:
常规API:2~5s
批量/大文件:10~30s
你想想看,读取超时是最容易误判的。服务端可能只是CPU高,但请求在队列里排队,客户端以为它死了。
特别注意: 读取超时不是“整个请求时间”,而是两次读取之间的等待时间。有些框架的读取超时会重新计时,如果服务端持续发小块数据,永远不会超时。这个大坑我踩过,线上慢查询拖垮了连接池,熔断却一直没触发。
建议配合响应时间监控,当平均读取耗时超过超时阈值的70%时,提前告警。
3.3 写入超时(Write Timeout)
客户端向服务端发送请求数据时,等待写入完成的超时时间。
通常发生在请求体很大(比如上传文件)或服务端接收窗口满时。
典型值:
常规请求:1~3s
大文件上传:30~60s
很多同学容易忽略写入超时。其实在网关层,请求体还没发完就超时了,服务端可能收到半截body,导致解析失败,返回400——这也算一次失败。
与熔断的关系:
写入超时通常意味着网络拥塞或连接池已满。我建议写入超时设置得比读取超时稍短一些,因为写入失败可以快速重试,而读取失败往往意味着业务逻辑已执行。
个人经验: 曾有一次线上事故,客户端写入超时设为5s,服务端连接池只有20个,突发上传请求时,大量写入超时堆积,熔断器在3分钟里触发了15次。后来把写入超时降到2s,配合连接池扩容,问题消失。
3.4 空闲超时(Idle Timeout)
连接池中空闲连接存活的最大时间。超过这个时间,连接会被关闭并从池中移除。
这个参数不直接产生失败,但它决定了连接池的新陈代谢速度。
典型值:
HTTP/1.1保持连接:30s~5min
数据库连接池(HikariCP/Druid):5~10min
嗯,这里要注意:空闲超时设得太长,连接池里全是老连接,可能被防火墙或中间设备掐断,导致连接“假活”。
假活危害: 客户端以为连接可用,实际服务端已经关闭了。当你发请求时,要么连接断开(Connection reset),要么超时。我曾在生产里排查过一个诡异现象——每30分钟出现一波连接超时,最后发现是AWS SLB的闲置超时是5分钟,而客户端空闲超时设了10分钟,导致大量假活。
空闲超时对熔断的影响是间接但关键的。假活连接会产生大量失败请求,瞬间填满熔断窗口。所以空闲超时要略小于网络中间设备的空闲超时。
3.5 四类超时对比速查表
| 超时类型 | 触发时机 | 典型值(内网) | 对熔断的直接程度 | 我常用的避坑口诀 |
|---|---|---|---|---|
| 连接超时 | TCP握手阶段 | 500ms~1s | 直接 + 快速 | “连不上就断,别等它恢复” |
| 读取超时 | 等待数据返回 | 2~5s | 直接 + 中速 | “读超时看百分比,别只看值” |
| 写入超时 | 发送请求体 | 1~3s | 直接 + 较快 | “写超时比读超时短,别让对方白忙” |
| 空闲超时 | 连接闲置时 | 30s~5min | 间接 + 滞后 | “空闲设小点,假活少一点” |
3.6 超时参数与熔断窗口的联动设计
光知道分类还不够,怎么搭配才能让熔断器灵敏且不误伤?
我分享一个实际项目里的参数矩阵:
// 典型微服务 HTTP 客户端参数示例(Feign + Hystrix)
connectionTimeout = 500ms
readTimeout = 2000ms
writeTimeout = 1000ms
idleTimeout = 30s
// 熔断器配置
circuitBreaker.sleepWindowInMilliseconds = 5000
circuitBreaker.requestVolumeThreshold = 10
circuitBreaker.errorThresholdPercentage = 50
这个配置下,如果连续5秒内有10次请求,超过一半超时或失败,熔断器就会跳闸。
注意看:空闲超时只有30s,所以连接池里的连接大部分都是“新鲜”的,假活概率极低。
调参顺序: 我习惯先定空闲超时(避免假活),再定连接超时(快速失败),然后根据服务端P99延迟调读/写超时,最后配熔断阈值。顺序乱了,排查起来很痛苦。
四种超时参数各自扮演不同角色,但它们共同的目标是帮助系统在异常发生时快速失败、减少资源浪费、并为熔断器提供准确的失败信号。记住,参数不是设完就完事,线上持续监控才是王道。