接口时不时超时,重启后能好一阵,日志没报错,问题藏在哪里?
接口时不时超时,重启后能好一阵,日志却没明显异常,这种情况多半不是业务逻辑错,而是连接池、线程池或底层资源被占满后没及时释放。重启会把这些占用强行清空,于是表现成“重启就好”。按 2026 年排查习惯,先把偶发超时和持续高延迟分开,再按资源占用、下游依赖、代码变更三个方向找证据。
- 偶发超时:大部分请求正常,某个时间窗内出现超时或明显变慢,重启后暂时缓解。优先查连接池、线程池、GC 停顿和下游抖动。
- 持续高延迟:所有请求从一开始就慢,重启后也没有明显变化。优先查代码性能、数据库慢 SQL、依赖服务容量。
先弄清重启到底恢复了什么
重启会重置连接池、线程池、文件句柄和本地缓存,也会打断积压任务队列。所以“重启就好”不代表修复,而是把一段时间累积的占用清零了。典型占用包括:一条慢查询占住数据库连接,或一个外部接口迟迟不返回,把业务线程全拖住。请求多半在等待连接或队列时被超时中断,还没进业务异常分支,所以日志里没有完整堆栈。因此,下次处理前先补重启前 5-10 分钟的池指标、线程数和 GC 样本,确认是哪类资源被占,再决定是否重启。
优先查连接池和线程池是否被占满
常见根因之一是池被占满。连接池占满时日志会提示 connection is not available;线程池占满时 CPU 不高,但请求排队时间越来越长。特征是池里有空闲资源就正常,池满就超时。如果池活跃数不高但仍然超时,就不要继续调池参数,应转向下游依赖或 GC。
经验区间供参考:连接池上限通常为业务峰值的 2~3 倍,前提是数据库端有余量;内部依赖超时可设 300ms~3s,外部服务可放宽到 5s 左右,但要配合熔断降级。
- 连接池:看等待连接时长和活跃数,找长时间占用不归还的调用。
- 线程池:看队列深度和拒绝数,业务池与框架池分开看。
- 慢 SQL:超时窗口与 slow log 对齐,有重叠先处理慢查询。
一次管理后台排查,只有重启记录表,没有池指标。我们让运维在下一发布窗口补上重启前 5 分钟的活跃采集;超时仍偶发,但拿到数据后发现是整点报表查询占用连接池约 20~40 分钟。调整查询后才闭环。常见区间里,连接等待超过 500ms 或线程排队超过 30% 就值得重点看。
再看下游依赖与重试叠加
接口还会调外部服务、缓存和消息队列。下游偶发变慢时,调用方超时太长,线程就会被挂住;多个上游同时等待,自己的线程池也会被拖垮。先用调用链看耗时分布,分清是单个请求慢还是每个都慢。
重试要谨慎:下游过载时,自动重试等于二次冲击。需要随机退避和次数上限,非幂等接口不该自动重试。
资源泄漏和 GC 停顿也要核
若延迟曲线随运行时间逐步爬升,重启后回低位,优先考虑内存或文件句柄泄漏。Full GC 会让线程暂停几十到几百毫秒,叠加下游超时就表现为偶发超时。看堆是否阶梯式上升、Full GC 是否变频繁、文件描述符是否逼近上限。先修泄漏再扩内存,否则只是把风险推迟。
排查证据链顺序
没有明确报错时,按下列顺序取证据,每次只改一个变量。同时调整连接池、GC 和超时参数,常会掩盖真实原因。
- 确认重启前 5-10 分钟有连接池、线程池、GC、下游耗时数据。
- 按连接池→线程池→下游→GC/泄漏顺序排查。
- 用时间线对齐超时窗口与慢 SQL、Full GC、下游错误。
- 锁定后小步修改,不同时改多个参数。
- 修复后观察 1~2 周,P99 不再有毛刺再关闭工单。
如果故障出现在一次新发布后,先把代码变更放进第一步核对;如果日志已有明确异常堆栈,则直接按堆栈定位,不机械走完整套步骤。
适用边界与成本对照
本文思路适用于“偶发超时、运行一段时间后出现、重启后缓解、日志无业务堆栈”的后端服务,尤其是有连接池、线程池和 GC 的 Java、Go、.NET 服务。低并发的管理后台出现类似问题时,先看数据库锁等待和网络抖动,不必先把所有连接池、线程池参数翻一遍。
- 适用:错误日志只有超时或连接提示,重启后首轮请求正常。
- 不适用:服务一启动就慢、重启无缓解,或异常堆栈直接指向业务代码。
处理路径可以做一组成本对照:直接调大连接池和超时,改动约 0.5~1 天,观察约 1 周,适合先恢复业务,但下个高峰可能复发;先补监控、等故障样本再定位,准备约 1~2 天,定位修复约 2 小时到 2 天,完整观察建议 2 周,成本通常高 2~4 倍,但能结束反复重启。如果线上已受影响,可先选择前者,事后仍要按证据链把根因找出来。
常见问题
日志没明显报错,为什么接口还会偶发超时?
请求通常在等待连接或线程队列时被超时中断,还没进入业务异常逻辑,所以没有显眼堆栈。需要从资源池占用、调用链时间线上找证据。
把超时时间调长一些能不能解决?
调长只让调用方等得更久。如果是池被占满,队列只会越积越长;要结合资源池指标,配合限流或熔断再调超时。
重启前忘了抓现场,后面还能定位吗?
能,但效率更低。先补齐重启前后监控,下次出现时保留线程堆栈、GC 日志和池快照;也可以先借助历史监控划出可能时间点。
连接池调大了一倍仍然偶发超时,是为什么?
调大池不等于降低单条连接的占用时长。慢 SQL 或下游调用卡住时,池再大也会被占满;应先缩短占用时间或让占用方及时释放。
-
上传目录跟着代码一起发版,图片全丢了,文件到底该存本地还是对象存储?
日期:2026年9月13日 阅读:101
-
刚保存完跳详情页,读到的还是旧记录,读写分离是不是都得走主库?
日期:2026年9月12日 阅读:43
-
定时任务单机跑得好好的,一上多台机器就重复执行,到底该从哪拦?
日期:2026年9月11日 阅读:33
-
表刚上线时用自增主键挺省事,真到分库那天改起来有多麻烦?
日期:2026年9月10日 阅读:73
-
调大数据库连接池后接口反而变慢,连接数到底设多大合适?
日期:2026年9月9日 阅读:87




