id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week
| id |
title |
type |
domain |
stack |
tags |
level |
prerequisites |
est_hours |
related |
week |
| cs.network-os.scenario.connection-troubleshooting |
线上连接问题排查:大量 TIME_WAIT、连接池耗尽、fd 用尽和事件循环阻塞 |
scenario |
cs |
|
| TIME_WAIT |
| 连接池 |
| 文件描述符 |
| 事件循环阻塞 |
| 超时 |
| 排查 |
|
intermediate |
| cs.network-os.http-tcp |
| cs.network-os.os-basics |
|
2 |
| cs.network-os.interview |
| devops.linux.scenario.incident-troubleshooting |
|
|
线上连接问题排查:大量 TIME_WAIT、连接池耗尽、fd 用尽和事件循环阻塞
业务背景与问题
AI Agent 服务(FastAPI)高峰期偶发大量超时,日志中出现:
- 调用模型网关报 “Cannot assign requested address”;
- 偶尔出现 “Too many open files”;
- 所有请求的延迟同时变高,包括健康检查。
约束
方案设计
- 看连接状态:
ss -s、ss -tan state time-wait | wc -l 发现几万个 TIME_WAIT,目标都是模型网关 → 代码中每次请求都新建 httpx.AsyncClient,用完就关闭,没有复用连接。修复:应用级共享一个客户端(连接池),设置池大小和 keep-alive。
- 看 fd:
ls /proc/<pid>/fd | wc -l 与 ulimit -n 对比 → 文件上传后临时文件没有关闭。修复:使用 with 管理资源;在监控中加入 fd 数量。
- 看事件循环:所有请求同时变慢,说明事件循环被阻塞 → 用 asyncio 调试模式 / 采样分析发现同步的 PDF 解析。修复:移到进程池(
run_in_executor)或任务队列。
- 超时与隔离:所有外部调用设置连接超时和读超时;对模型网关设置并发上限(信号量),防止一个慢依赖耗尽所有资源。
- 验证:压测对比修复前后的 TIME_WAIT 数量、fd 数量、P99 延迟。
关键代码
相关原理:网络基础、操作系统基础;Linux 排查命令见 Linux 线上排查。
取舍
| 选择 |
优点 |
缺点 |
| 复用连接(本方案) |
根治 TIME_WAIT,同时降低延迟(省去握手) |
要管理客户端生命周期 |
| 调整内核参数(端口范围、TIME_WAIT 复用) |
立刻见效 |
治标不治本,有副作用,容器内往往无权限 |
| 增加实例 |
简单 |
掩盖问题,成本上升 |
易错点
- 看到 TIME_WAIT 就认为是服务器的问题——它出现在主动关闭的一方。
- 共享的客户端没有设置池上限,慢依赖拖垮整个服务。
- 只设置了总超时,没有区分连接超时和读超时(流式响应的读超时要考虑 token 间隔)。
面试怎么讲
“Agent 服务高峰期出现‘Cannot assign requested address’,用 ss 看到几万个 TIME_WAIT 指向模型网关,原因是每次请求新建 HTTP 客户端。改成应用级共享客户端并配置连接池和分阶段超时后,TIME_WAIT 基本消失,延迟也下降了。另外发现同步 PDF 解析阻塞事件循环,导致所有请求同时变慢,移到进程池解决。修复后用压测对比了连接数、fd 数和 P99。”