From 46ea3e707b9abae918e3dd3b1fb2e66150f66890 Mon Sep 17 00:00:00 2001 From: Done-0 Date: Sat, 10 Jan 2026 22:12:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(provider-pool):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E8=AE=A1=E6=95=B0=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=B9=B6=E5=8F=91=E8=AF=B7=E6=B1=82=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E8=AF=AF=E5=88=A4=20unhealthy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - 多个项目并发请求时,临时性 500 错误会快速累计 - 即使内部重试成功,错误计数已经触发 unhealthy 标记 解决方案: - 引入 10 秒滑动窗口机制 - 超过窗口期的错误重置计数,而不是累加 - 只有窗口期内连续失败才标记 unhealthy --- src/providers/provider-pool-manager.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/providers/provider-pool-manager.js b/src/providers/provider-pool-manager.js index 8c777a3..cc618fc 100644 --- a/src/providers/provider-pool-manager.js +++ b/src/providers/provider-pool-manager.js @@ -398,11 +398,21 @@ export class ProviderPoolManager { const provider = this._findProvider(providerType, providerConfig.uuid); if (provider) { - provider.config.errorCount++; + const now = Date.now(); + const lastErrorTime = provider.config.lastErrorTime ? new Date(provider.config.lastErrorTime).getTime() : 0; + const errorWindowMs = 10000; // 10 秒窗口期 + + // 如果距离上次错误超过窗口期,重置错误计数 + if (now - lastErrorTime > errorWindowMs) { + provider.config.errorCount = 1; + } else { + provider.config.errorCount++; + } + provider.config.lastErrorTime = new Date().toISOString(); // 更新 lastUsed 时间,避免因 LRU 策略导致失败节点被重复选中 provider.config.lastUsed = new Date().toISOString(); - + // 保存错误信息 if (errorMessage) { provider.config.lastErrorMessage = errorMessage; @@ -414,7 +424,7 @@ export class ProviderPoolManager { } else { this._log('warn', `Provider ${providerConfig.uuid} for type ${providerType} error count: ${provider.config.errorCount}/${this.maxErrorCount}. Still healthy.`); } - + this._debouncedSave(providerType); } }