From f1b5afbf5ca4a1e627b48d3639329acd66993e5b Mon Sep 17 00:00:00 2001 From: Sakura-RanChen <1908198662@qq.com> Date: Mon, 5 Jan 2026 17:50:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A6=81=E7=94=A8httpx=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E6=B1=A0=E5=B9=B6=E6=98=BE=E5=BC=8F=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E9=98=B2=E6=AD=A2=E8=BF=9E=E6=8E=A5=E6=B3=84?= =?UTF-8?q?=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/manage_api_client.py | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/main/xiaozhi-server/config/manage_api_client.py b/main/xiaozhi-server/config/manage_api_client.py index f899d61c..a9d8d601 100644 --- a/main/xiaozhi-server/config/manage_api_client.py +++ b/main/xiaozhi-server/config/manage_api_client.py @@ -60,6 +60,10 @@ class ManageApiClient: # 为每个事件循环创建独立的客户端 if loop_id not in cls._async_clients: + # 服务端可能主动关闭连接,httpx 连接池无法正确检测和清理 + limits = httpx.Limits( + max_keepalive_connections=0, # 禁用 keep-alive,每次都新建连接 + ) cls._async_clients[loop_id] = httpx.AsyncClient( base_url=cls.config.get("url"), headers={ @@ -68,6 +72,7 @@ class ManageApiClient: "Authorization": "Bearer " + cls._secret, }, timeout=cls.config.get("timeout", 30), + limits=limits, # 使用限制 ) return cls._async_clients[loop_id] except RuntimeError: @@ -80,21 +85,27 @@ class ManageApiClient: # 确保客户端已创建 client = await cls._ensure_async_client() endpoint = endpoint.lstrip("/") - response = await client.request(method, endpoint, **kwargs) - response.raise_for_status() + response = None + try: + response = await client.request(method, endpoint, **kwargs) + response.raise_for_status() - result = response.json() + result = response.json() - # 处理API返回的业务错误 - if result.get("code") == 10041: - raise DeviceNotFoundException(result.get("msg")) - elif result.get("code") == 10042: - raise DeviceBindException(result.get("msg")) - elif result.get("code") != 0: - raise Exception(f"API返回错误: {result.get('msg', '未知错误')}") + # 处理API返回的业务错误 + if result.get("code") == 10041: + raise DeviceNotFoundException(result.get("msg")) + elif result.get("code") == 10042: + raise DeviceBindException(result.get("msg")) + elif result.get("code") != 0: + raise Exception(f"API返回错误: {result.get('msg', '未知错误')}") - # 返回成功数据 - return result.get("data") if result.get("code") == 0 else None + # 返回成功数据 + return result.get("data") if result.get("code") == 0 else None + finally: + # 确保响应被关闭(即使异常也会执行) + if response is not None: + await response.aclose() @classmethod def _should_retry(cls, exception: Exception) -> bool: