【Bug已解决】[Bug]: API Connection Error after concurrent API calls 解决方案
【Bug已解决】[Bug]: API Connection Error after concurrent API calls 解决方案一、现象长什么样用客户端高并发打 vLLM 的 OpenAI 兼容 API/v1/chat/completions或/v1/completions时并发量一上去就出现连接错误requests.exceptions.ConnectionError: (Connection aborted., BrokenPipeError(...))或aiohttp.client_exceptions.ClientOSError: [Errno 24] Too many open files或客户端侧httpx.ConnectError: [Errno 60] Operation timed out几个典型表征只在并发高时出现串行/低并发正常说明问题在连接数 / 文件描述符 / 端口复用这类资源上限而非单次请求逻辑。错误是连接层ConnectionError / BrokenPipe / Too many open files不是业务层服务端可能在高并发下用完了文件描述符fd、或没用 keep-alive 导致 TIME_WAIT 堆积、或事件循环被连接建立压垮。服务端可能伴随OSError: [Errno 24] Too many open files这是典型 fd 耗尽每个 TCP 连接占一个 fd并发数 × 每请求连接数超过系统ulimit -n。这不是模型问题而是API server 的连接/资源处理能力在高并发下被耗尽。下面给出定位与修复客户端连接池 服务端 fd/keep-alive 调优。二、背景HTTP 服务在高并发下的连接资源每个 TCP 连接占用一个文件描述符fd。Linux 默认ulimit -n可能是 1024vLLM 的 uvicorn/fastapi 进程若并发接几千连接fd 直接耗尽 →Too many open files→ 新连接被拒 / BrokenPipe。短连接无 keep-alive会留大量 TIME_WAIT每个请求建连断连端口/连接表堆积导致Cannot assign requested address或连接超时。客户端没用连接池每次请求新建requests.Session/ 新httpx.Client连接不复用fd 暴涨。vLLM 默认用 uvicorn 起服务并发连接上限受 fd 和系统 backlog 影响。修复分两端服务端调大ulimit -n、开 keep-alive、限制并发或靠队列排队而非无限制接连接客户端用连接池requests.Session/httpx.AsyncClient复用 限并发 指数退避重试。下面用可运行代码实现客户端连接池 服务端 fd 检测。三、根因拆成三条根因fd 耗尽服务端并发连接数超过进程 fd 上限默认 1024新连接accept失败 →Too many open files/ BrokenPipe。根因是服务端 fd 上限过低 短连接不回收。客户端不复用连接客户端每次请求新建连接没用 Session/Client连接数 请求数fd 在服务端和客户端同时暴涨。根因是缺少连接池 keep-alive 复用。无并发限制 / 重试风暴客户端无脑并发 失败后立刻重试连接数在重试中指数放大把服务端压垮。根因是缺少并发上限 退避重试。修复方向服务端调大 fd 开 keep-alive客户端用连接池复用 Semaphore限并发 指数退避重试。四、最小可运行复现下面复现客户端无连接池导致连接数暴涨的判定逻辑import threading class NaiveClient: 现状每次请求都建新连接连接不复用。 def __init__(self): self.open_connections 0 self._lock threading.Lock() def request(self): with self._lock: self.open_connections 1 # 每次新建 # ... 真实请求 ... with self._lock: self.open_connections - 1 def simulate_concurrent(client, n): threads [] def job(): # 串行化统计峰值朴素客户端峰值 ≈ 并发数 client.request() for _ in range(n): t threading.Thread(targetjob); t.start(); threads.append(t) for t in threads: t.join() c NaiveClient() # 若 n2000且服务端 fd 上限 1024峰值连接会撑爆 print(朴素客户端并发 2000 时服务端需承受约 2000 并发连接易超 fd 上限)真实场景里这 2000 并发连接会直接把服务端 fd 吃满。下面用连接池 限并发修复。五、解决方案第一层最小直接修复最小修复客户端用连接池复用 TCP 连接Semaphore限制并发 指数退避重试。import asyncio import httpx class PooledClient: 带连接池 并发限制 退避重试的客户端。 def __init__(self, base_url, max_concurrency64, max_connections64): self._sem asyncio.Semaphore(max_concurrency) # httpx.AsyncClient 内部维护连接池keep-alive 复用 self._client httpx.AsyncClient(base_urlbase_url, limitshttpx.Limits( max_connectionsmax_connections, max_keepalive_connectionsmax_connections), timeouthttpx.Timeout(60.0)) async def chat(self, payload, retries3): for attempt in range(retries): async with self._sem: # 限制并发 try: r await self._client.post(/v1/chat/completions, jsonpayload) r.raise_for_status() return r.json() except (httpx.ConnectError, httpx.TransportError) as e: if attempt retries - 1: raise # 指数退避避免重试风暴 await asyncio.sleep(0.5 * (2 ** attempt)) async def run_pooled(base_url, n): client PooledClient(base_url, max_concurrency64) tasks [client.chat({model: x, messages: []}) for _ in range(n)] # 并发被信号量限到 64连接池复用fd 稳定 return await asyncio.gather(*tasks, return_exceptionsTrue) # 用法 # asyncio.run(run_pooled(http://localhost:8000, 2000))这一层改动让客户端并发被限制、连接被复用服务端承受的并发连接数稳定在max_connections64而非 2000fd 不再耗尽。六、解决方案第二层结构化改进把服务端 fd / keep-alive 调优也做成结构化检测与配置两端配合客户端限并发 服务端提 fd 开 keep-alive。import resource import os def server_fd_guard(min_fd8192): 服务端启动期检测并尽量提高 fd 上限。 soft, hard resource.getrlimit(resource.RLIMIT_NOFILE) if soft min_fd: new_soft min(min_fd, hard) try: resource.setrlimit(resource.RLIMIT_NOFILE, (new_soft, hard)) except ValueError: print(f[warn] 无法提高到 {min_fd}当前软限 {soft}硬限 {hard}) cur_soft, _ resource.getrlimit(resource.RLIMIT_NOFILE) return cur_soft def report_uvicorn_tuning(): 给出 uvicorn 启动建议keep-alive 合理的 backlog。 return { keep_alive: 30, # 开 keep-alive复用连接 backlog: 2048, # 接受队列长度 # uvicorn 启动--limit-concurrency 按 GPU 数限制避免无限制接连接 limit_concurrency: 256, } # 用法服务端 main 入口最早调用 fd server_fd_guard(8192) print(服务端可用 fd 软限:, fd) print(uvicorn 建议:, report_uvicorn_tuning())server_fd_guard在服务端启动早期提高 fd 上限受系统硬限约束report_uvicorn_tuning给出 keep-alive 并发限制建议两端配合消掉高并发连接错误。七、解决方案第三层断言 / CI 守护并发连接错误最怕线上高并发才暴露。用断言守两条不变量def check_concurrency_invariants(base_url, n, max_conn): # 不变量 1客户端并发被信号量限制实际并发连接 max_conn # 用 httpx.Limits 保证连接池上限 client httpx.AsyncClient(base_urlbase_url, limitshttpx.Limits(max_connectionsmax_conn)) assert client._limits.max_connections max_conn # 不变量 2服务端 fd 软限必须 预期并发连接 soft, _ resource.getrlimit(resource.RLIMIT_NOFILE) assert soft max_conn, ffd 软限 {soft} 应 并发 {max_conn} return True def test_concurrency_safe(): import resource check_concurrency_invariants(http://x, 2000, max_conn64) print(OK: 并发连接不变量通过) if __name__ __main__: test_concurrency_safe()把test_concurrency_safe接进 CI用本地 mock server 或只做配置校验锁死客户端限并发 / 服务端 fd 足够。八、排查清单高并发打 vLLM API 报 Connection Error按序查看错误类型Too many open files→ fd 耗尽BrokenPipe→ 服务端在请求中途断了连接常因 fd 满后 accept 失败ConnectError/Timeout→ 连接建立被压垮或端口耗尽。客户端必须用连接池用requests.Session/httpx.AsyncClient内部 keep-alive千万不要每次请求新建 client。连接复用能把 fd 数降一个数量级。限制客户端并发用Semaphoreasyncio或线程池把并发控制在服务端能承受的范围如 64~256别无脑并发 2000。退避重试防风暴连接错误重试要用指数退避且限制重试次数避免失败→立刻重试→连接数翻倍的雪崩。服务端提 fd 上限ulimit -n 8192或写在启动脚本 / systemd 里server_fd_guard在启动期尽量提高软限。服务端开 keep-alive 限并发uvicorn 设--timeout-keep-alive 30复用连接必要时--limit-concurrency按 GPU 数限制避免无限制接连接把 fd 吃满。CI 接test_concurrency_safe校验客户端限并发 / 服务端 fd 足够高并发场景前先过这道闸。九、小结高并发打 vLLM API 报 Connection Error 的根因是连接资源fd / 连接数在高并发下被耗尽服务端 fd 上限过低 客户端不复用连接 无并发限制/重试风暴。三层修复第一层PooledClient用 httpx 连接池复用 TCP 连接 Semaphore限并发 指数退避重试把服务端承受的并发连接数稳定在池上限而非请求数第二层server_fd_guard服务端启动期提高 fd 软限report_uvicorn_tuning给出 keep-alive 并发限制建议两端配合第三层CI 断言守住客户端限并发 / 服务端 fd 足够高并发前先过闸。落实后vLLM API 在高并发下连接被复用、并发被限制、fd 足够不再因Too many open files/BrokenPipe拒绝连接。

相关新闻

sdm性能优化指南:提升Raspberry Pi镜像烧录速度的5个实用技巧

sdm性能优化指南:提升Raspberry Pi镜像烧录速度的5个实用技巧

sdm性能优化指南:提升Raspberry Pi镜像烧录速度的5个实用技巧 【免费下载链接】sdm Raspberry Pi SD Card Image Manager 项目地址: https://gitcode.com/gh_mirrors/sdm1/sdm sdm作为高效的Raspberry Pi SD卡镜像管理器,其烧录速度直接影响开发效…

2026/10/31 0:34:19 阅读更多 →
紧凑型设备中的红外测温方案: S-D1贴片传感器在IoT产品中的应用分析

紧凑型设备中的红外测温方案: S-D1贴片传感器在IoT产品中的应用分析

IoT设备小型化趋势下的测温挑战IoT设备的产品形态正在发生深刻变化——从工业级的大型网关到消费级的可穿戴设备、从固定安装的传感器节点到随身携带的智能终端,“更小、更薄、更省电”是贯穿其中的主旋律。这一趋势对温度传感器提出了一个核心矛盾:传统…

2026/11/10 3:35:00 阅读更多 →
Java面试进阶:从八股文到系统设计,掌握AI时代后端工程师核心能力

Java面试进阶:从八股文到系统设计,掌握AI时代后端工程师核心能力

1. 先搞清楚现在面试到底在考什么,别盲目背题 如果你现在还在用三年前的套路准备Java面试,大概率会碰壁。现在的面试,尤其是面对AI工具普及和降本增效的大环境,已经不再是单纯问你“HashMap原理”或者背出“Spring Bean生命周期”就能过关了。面试官更看重的是 你能否把技…

2026/11/10 6:35:33 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/12 5:00:00 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/12 5:13:20 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/12 5:13:20 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/12 18:22:26 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/12 18:22:25 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/12 5:13:20 阅读更多 →

日新闻

周新闻

月新闻