Repository navigation
feat(llm): LLM 调用复用 HTTP 连接,不再每次重新握手 (#206) - #207
Merged
Merged
Conversation
三个传输适配器(OpenAI 兼容 / anthropic / gemini)原来每次请求都新建一个 HTTP 客户端、用完就扔,每次 LLM 调用都多做一次 TCP + TLS 握手。现在共用 一个客户端:httpx 的连接池本来就按「协议+主机+端口」分开管,一个客户端 能同时服务多家厂商,空闲连接保活 5 分钟(httpx 自带的 5 秒对间隔几十秒的 调用等于没复用)。 - 连接上限默认 16(LLM_HTTP_POOL_CONNECTIONS),盖住主链路 4 并发 + 评测 最多 8 并发 + 探测;超出时排队等空闲连接,不报错。 - 单次调用的超时还是按请求下发,每个模型各自生效。 - 应用停机时在后台任务收尾之后关掉客户端,在途调用先用完手上的连接。 - 客户端按事件循环隔离:测试框架每个用例一个新循环,跨循环复用会报 「Event loop is closed」;生产只有一个循环,不受影响。
Owner
Author
复核状态说明计划中的独立复核(全新上下文子代理,同 #205)因子代理用量达到账号周期上限无法执行(额度 2026-11-05 恢复)。owner 指示继续——本评论是实现者自审,不构成独立复核;如需要,额度恢复后可补一次真正的独立复核。 实现者自审(对照原定复核清单,逐项带代码证据)
结论:未发现需要修复的问题;1 项 P3(cookie jar 共享,与既有行为一致)记录在案。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
做了什么
关闭 #206。三个传输适配器原来每次 LLM 调用都新建一个
httpx.AsyncClient、用完就扔——每次调用都多一次 TCP + TLS 握手。这是 #181 试点时就记录的「已知未做」,自研层成为唯一路径(#200 / #204)后它落在每一次生产调用上。services/llm/adapters/http_pool.py:共享客户端,按事件循环惰性创建。httpx 的连接池按「协议+主机+端口」分池,一个客户端能同时服务多家厂商。client.post(..., timeout=)),每个模型各自生效,语义与原来逐请求建客户端完全一致。LLM_HTTP_POOL_CONNECTIONS(默认 16:主链路 4 并发 + ��测 8 并发 + 探测,超出排队不报错)、LLM_HTTP_KEEPALIVE_SECONDS(默认 300——httpx 自带只保活 5 秒,对间隔几十秒的 LLM 调用等于没复用)。为什么按事件循环隔离
pytest-asyncio 每个用例一个新循环,跨循环复用客户端会在已关闭的循环上发请求。客户端同时记住创建它的循环(弱引用),换循环就新建;生产进程只有一个循环,这条路径只对测试有意义。
不变的东西
URL 拼接、请求体、请求头、错误分类、用量提取一行没动;编排层的
asyncio.wait_for外层截止时间照旧。Verification
make lint全过(ruff / 分层 / 评分镜像 / 刊名 / tsc)。tests/test_llm_http_pool.py:同循环复用同一客户端;配置上限与保活进客户端;关闭后再取是新的;换循环不复用旧客户端;适配器两次调用只建一个客户端;超时值随请求写进 httpx 的request.extensions["timeout"](MockTransport 不做超时强制,所以验证的是下发而不是伪造计时)。httpx.AsyncClient注入 MockTransport)不改语义继续通过——池在每个用例的新循环上惰性创建,拿到的就是 patch 后的构造器。未覆盖:真实网络上的复用收益(握手次数/延迟)本地只有 mock,合并后可对线上模型连跑两次 ping 观察第二次延迟下降。
关联:#181(首次记录缺口)、#204(退役后成为唯一路径)