From 0fb11880a4bd4eb7caba57218e9ebdc0b056254f Mon Sep 17 00:00:00 2001 From: Aqr-K <1210498076@qq.com> Date: Mon, 11 May 2026 03:17:47 -0400 Subject: [PATCH] =?UTF-8?q?perf(http):=20AsyncRequestUtils=20=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=90=AF=E7=94=A8=20HTTP/2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为 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 单点关闭。 --- app/utils/http.py | 14 ++++++++++++++ requirements.in | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/utils/http.py b/app/utils/http.py index 4f1b23b2..c2ce5323 100644 --- a/app/utils/http.py +++ b/app/utils/http.py @@ -52,6 +52,7 @@ class _NonClosingTransportProxy(httpx.AsyncBaseTransport): _SharedTransportKey = Tuple[ Optional[str], # proxy Union[bool, str], # verify + bool, # http2 int, # max_keepalive_connections int, # max_connections int, # keepalive_expiry @@ -76,6 +77,7 @@ _pending_eviction_tasks: set[asyncio.Task] = set() def _get_shared_async_transport( proxy: Optional[str], verify: Union[bool, str], + http2: bool, max_keepalive_connections: int, max_connections: int, keepalive_expiry: int, @@ -104,6 +106,7 @@ def _get_shared_async_transport( key: _SharedTransportKey = ( proxy, verify, + http2, max_keepalive_connections, max_connections, keepalive_expiry, @@ -115,6 +118,7 @@ def _get_shared_async_transport( # 首次见到这个配置,创建新的共享 transport 桶 transport = httpx.AsyncHTTPTransport( + http2=http2, proxy=proxy, verify=verify, limits=httpx.Limits( @@ -786,6 +790,7 @@ class AsyncRequestUtils: accept_type: str = None, verify: Union[bool, str] = False, follow_redirects: bool = True, + http2: bool = True, max_keepalive_connections: int = _DEFAULT_MAX_KEEPALIVE_CONNECTIONS, max_connections: int = _DEFAULT_MAX_CONNECTIONS, keepalive_expiry: int = _DEFAULT_KEEPALIVE_EXPIRY, @@ -802,6 +807,10 @@ class AsyncRequestUtils: :param accept_type: Accept头部信息,默认为 "application/json" :param verify: 是否校验证书 :param follow_redirects: 客户端默认是否跟随重定向 + :param http2: 是否启用 HTTP/2(默认 True)。基于 TLS ALPN 协商:服务端 + 支持 h2 时复用流多路复用,不支持(含明文 HTTP、老 nginx/Apache) + 自动透明回落 HTTP/1.1。如遇个别站点 h2 实现异常,可显式传 + http2=False 单独关闭。 :param max_keepalive_connections: 共享 AsyncHTTPTransport 的最大 keep-alive 连接数 :param max_connections: 共享 AsyncHTTPTransport 的最大连接数 :param keepalive_expiry: 共享 AsyncHTTPTransport 的 keep-alive 连接过期时间(秒) @@ -811,6 +820,7 @@ class AsyncRequestUtils: self._timeout = timeout or 20 self._verify = verify self._follow_redirects = follow_redirects + self._http2 = http2 self._max_keepalive_connections = max_keepalive_connections self._max_connections = max_connections self._keepalive_expiry = keepalive_expiry @@ -915,6 +925,7 @@ class AsyncRequestUtils: transport = _get_shared_async_transport( proxy=self._proxies, verify=self._verify, + http2=self._http2, max_keepalive_connections=self._max_keepalive_connections, max_connections=self._max_connections, keepalive_expiry=self._keepalive_expiry, @@ -934,6 +945,7 @@ class AsyncRequestUtils: # 兜底:没有运行中的事件循环时,临时客户端走完即关 async with httpx.AsyncClient( + http2=self._http2, proxy=self._proxies, timeout=self._timeout, verify=self._verify, @@ -1116,6 +1128,7 @@ class AsyncRequestUtils: transport = _get_shared_async_transport( proxy=self._proxies, verify=self._verify, + http2=self._http2, max_keepalive_connections=self._max_keepalive_connections, max_connections=self._max_connections, keepalive_expiry=self._keepalive_expiry, @@ -1132,6 +1145,7 @@ class AsyncRequestUtils: else: client = await stack.enter_async_context( httpx.AsyncClient( + http2=self._http2, proxy=self._proxies, timeout=self._timeout, verify=self._verify, diff --git a/requirements.in b/requirements.in index a095b549..58800e5f 100644 --- a/requirements.in +++ b/requirements.in @@ -75,7 +75,7 @@ setuptools~=78.1.0 pympler~=1.1 smbprotocol~=1.15.0 setproctitle~=1.3.6 -httpx[socks]~=0.28.1 +httpx[socks,http2]~=0.28.1 langchain~=1.2.15 langchain-core~=1.3.2 langchain-community~=0.4.1