"""共享的 httpx.AsyncClient。 历史问题:后端每次访问 chatlog.exe(127.0.0.1:5030)都新建一个 AsyncClient, 用完即关,没有 keep-alive。打开一个群聊会瞬间产生几十条短连接(图片代理、 头像查询等),在 Windows 上会堆积 TIME_WAIT / 耗尽临时端口,导致“用一会儿就卡”。 这里改为全后端共享一个带连接池的 client,复用 keep-alive 连接,连接建立开销 和端口占用都大幅下降。在 lifespan 关闭时统一释放。 """ from __future__ import annotations import httpx _client: httpx.AsyncClient | None = None def shared_client() -> httpx.AsyncClient: """返回进程级共享的 AsyncClient(惰性创建)。 - trust_env=False:与原各处调用保持一致,不读系统代理,避免本地回环被代理拦截。 - follow_redirects=True:媒体/文件接口需要;普通 api 调用无重定向,无副作用。 - limits:保持 keep-alive 连接,避免每请求新建连接。 单次请求可通过 client.get(..., timeout=...) 覆盖超时。 """ global _client if _client is None or _client.is_closed: _client = httpx.AsyncClient( trust_env=False, follow_redirects=True, timeout=httpx.Timeout(30.0, connect=5.0), limits=httpx.Limits( max_keepalive_connections=32, max_connections=128, keepalive_expiry=30.0, ), ) return _client async def close_shared_client() -> None: """在应用关闭时释放共享 client。""" global _client if _client is not None and not _client.is_closed: await _client.aclose() _client = None