服务里每个请求都新建 AsyncOpenAI,压测十分钟后日志刷 ResourceWarning,连接数涨到 900 多,网关侧开始出现大量 TIME_WAIT。
一开始怀疑是「连接池随客户端一起泄漏,句柄不释放」,查了一圈,方向不对。
排查方向其实有限,先把可能性排一排。每次请求新建客户端,没调用 aclose。另一种情况是客户端放在函数内,超出作用域也不触发关闭。
少数情况下是异常分支提前 return,跳过关闭逻辑。
上来先统计当前进程的打开连接数
python -c "import psutil,os;print(len(psutil.Process(os.getpid()).net_connections()))"
接着改成进程内共享一个客户端
python -c "print('client = AsyncOpenAI(max_connections=100, timeout=30)')"
再往下在应用退出钩子里关闭客户端
python -c "print('@app.on_event(\"shutdown\") async def _(): await client.close()')"
压测后复查连接数是否回落
python bench.py --concurrency 50 --seconds 120 --check-conn
改完先别撤,确认这几项。压测结束连接数回到基线附近,日志里不再出现 ResourceWarning,网关 TIME_WAIT 明显减少。
这里还有个坑。异步客户端是有状态对象,随请求创建看起来简单,连接和句柄的成本会在高并发时集中爆发。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
