From 0bab72ea981ffedfe343272008c3a48159047c3d Mon Sep 17 00:00:00 2001 From: v6ole Date: Fri, 12 Jun 2026 11:15:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20/api/health=20404?= =?UTF-8?q?=20=E5=92=8C=E6=89=AB=E6=8F=8F/=E5=8F=91=E7=8E=B0=20500=20?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. /api/health 404: 前端 fetchVersion 调用 /api/health,但后端只有 /health。 OpenResty 保留完整路径,需要在后端添加 /api/health 端点。 2. 扫描/发现 500: check_service.py 的连接池 _get_cached_ssh 缓存了 SSH 连接,但调用方在 finally 中 ssh.close() 关闭连接。第二次调用 从缓存拿到已关闭的连接导致执行失败。改为异常时清除缓存、正常时 保留连接(5分钟TTL自动管理生命周期)。 Co-Authored-By: Claude --- backend/app/main.py | 6 ++++++ backend/app/services/check_service.py | 16 ++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/app/main.py b/backend/app/main.py index 370d548..db524b0 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -112,3 +112,9 @@ def health_check(): status["db"] = "error" status["status"] = "degraded" return status + + +@app.get("/api/health") +def api_health_check(): + """API 路径下的健康检查(用于前端通过 /api/ 代理访问)""" + return health_check() diff --git a/backend/app/services/check_service.py b/backend/app/services/check_service.py index a3bcd56..280c57d 100644 --- a/backend/app/services/check_service.py +++ b/backend/app/services/check_service.py @@ -103,8 +103,10 @@ class CheckService: "online": online_count, "offline": offline_count, } - finally: - ssh.close() + except Exception: + # 连接异常时清除缓存,下次自动重连 + _conn_pool.pop(olt_id, None) + raise def check_single_device(self, device_id: int) -> Dict: """通过 SSH 单独查询一台 ONU 设备的当前状态和距离。 @@ -251,8 +253,9 @@ class CheckService: "offline": offline_count, "new_discovered": new_count, } - finally: - ssh.close() + except Exception: + _conn_pool.pop(olt_id, None) + raise async def scan_olt(self, olt_id: int) -> Dict: """仅扫描 OLT,返回发现的设备列表(不写入数据库)""" @@ -300,8 +303,9 @@ class CheckService: "devices": devices, "duplicates": duplicates, } - finally: - ssh.close() + except Exception: + _conn_pool.pop(olt_id, None) + raise def _save_duplicate_macs(self, olt_id: int, duplicate_dict: dict): for mac, records in duplicate_dict.items():