Aqr-K
|
0fb11880a4
|
perf(http): AsyncRequestUtils 默认启用 HTTP/2
为 AsyncRequestUtils 增加 http2: bool = True 参数(默认开启),
内部贯穿到 _get_shared_async_transport 与 path C 兜底 AsyncClient。
http2 加入共享 AsyncHTTPTransport 桶 key,让不同 h2 设置自动隔离。
启用基于 TLS ALPN:服务端宣告支持 h2 时切到 HTTP/2 多路复用;
不支持(含明文 HTTP、老 nginx/Apache)透明回落 HTTP/1.1。如个别
站点 h2 实现异常,调用方传 http2=False 单独关闭。
依赖:httpx extras 由 [socks] 扩展为 [socks,http2],引入纯 Python
包 h2 / hpack / hyperframe(无原生扩展)。
真实 TMDB 压测(30 部美剧 × 每部 50 集 = 3060 请求/版本):
HTTP/1.1 52.0s → HTTP/2 27.6s,节省 24.4s(1.88×)。
单请求 p95 由 96.1ms 降至 20.1ms,长尾大幅收敛。
公共 API 表面零变动;插件可按需 http2=False 单点关闭。
|
2026-05-11 17:15:23 +08:00 |
|
Aqr-K
|
c745616495
|
perf(http): 异步 HTTP 引入共享 AsyncHTTPTransport,复用 TCP/TLS 握手
AsyncRequestUtils 使用按事件循环弱引用持有的共享
AsyncHTTPTransport 作为底层连接池与 TLS 会话;每次请求创建轻量
AsyncClient 承载本次 cookie jar、timeout、follow_redirects,
用完即销毁。共享 transport 由 _NonClosingTransportProxy 包装后
注入 AsyncClient,吞掉 AsyncClient 退出时向底层 transport
传播的 __aexit__/aclose,使底层连接池跨调用持久,从而真正复用
TCP/TLS 握手。
设计要点:
- 共享 transport 桶按 (proxy, verify, max_keepalive_connections,
max_connections, keepalive_expiry) 区分;每事件循环 32 桶 LRU
上限,超出后异步关闭最久未用桶;关闭 task 由模块级强引用集合
持有以兼容 Python 3.11+ 的任务 GC 行为。
- 通过 FastAPI lifespan shutdown 调用 aclose_shared_async_transports
集中释放底层 transport,避免 ResourceWarning。
- AsyncRequestUtils.request 走三条 path:用户自管 client / 共享
transport + per-call AsyncClient / 兜底临时 client。三条路径
cookie 语义一致;后两条因 per-call AsyncClient 生命周期局限于
单次调用,天然不积累 Set-Cookie,避免跨调用 jar 演化串扰。
- _make_request 对幂等方法(GET/HEAD/OPTIONS)在
RemoteProtocolError / ReadError / WriteError 时单次重试,
容忍 keep-alive stale 连接命中;非幂等方法不重试,但记录
debug 日志。
- get_stream 使用 httpx.AsyncClient.stream() 标准流式 API,与
request 共用三条 path 的 client 选择逻辑;幂等单次重试;
yield 体异常透传给 stream 的 __aexit__。
公共 API 表面零变动。插件可通过 max_keepalive_connections /
max_connections / keepalive_expiry 三个 limits 参数为自己定制
连接池容量与握手有效期。
TMDB 真实压测(10 部美剧 × 每部 50 集,1020 请求):
61.96s → 18.15s(3.41×),单请求 p95 149.6ms → 38.1ms。
|
2026-05-11 08:46:40 +08:00 |
|