diff --git a/src/core/config-manager.js b/src/core/config-manager.js index cc68110..fe1d018 100644 --- a/src/core/config-manager.js +++ b/src/core/config-manager.js @@ -79,7 +79,7 @@ export async function initializeConfig(args = process.argv.slice(2), configFileP CRON_NEAR_MINUTES: 15, CRON_REFRESH_TOKEN: false, PROVIDER_POOLS_FILE_PATH: null, // 新增号池配置文件路径 - MAX_ERROR_COUNT: 3, // 提供商最大错误次数 + MAX_ERROR_COUNT: 10, // 提供商最大错误次数 providerFallbackChain: {} // 跨类型 Fallback 链配置 }; console.log('[Config] Using default configuration.'); diff --git a/src/providers/provider-pool-manager.js b/src/providers/provider-pool-manager.js index eaee054..c430a1d 100644 --- a/src/providers/provider-pool-manager.js +++ b/src/providers/provider-pool-manager.js @@ -30,7 +30,7 @@ export class ProviderPoolManager { this.providerStatus = {}; // Tracks health and usage for each provider instance this.roundRobinIndex = {}; // Tracks the current index for round-robin selection for each provider type // 使用 ?? 运算符确保 0 也能被正确设置,而不是被 || 替换为默认值 - this.maxErrorCount = options.maxErrorCount ?? 3; // Default to 3 errors before marking unhealthy + this.maxErrorCount = options.maxErrorCount ?? 10; // Default to 10 errors before marking unhealthy this.healthCheckInterval = options.healthCheckInterval ?? 10 * 60 * 1000; // Default to 10 minutes // 日志级别控制 @@ -974,6 +974,7 @@ export class ProviderPoolManager { provider.config.isHealthy = true; provider.config.errorCount = 0; provider.config.refreshCount = 0; + provider.config.needsRefresh = false; provider.config.lastErrorTime = null; provider.config.lastErrorMessage = null; diff --git a/src/ui-modules/provider-api.js b/src/ui-modules/provider-api.js index b7d25c6..2b1adcc 100644 --- a/src/ui-modules/provider-api.js +++ b/src/ui-modules/provider-api.js @@ -429,6 +429,7 @@ export async function handleResetProviderHealth(req, res, currentConfig, provide provider.isHealthy = true; provider.errorCount = 0; provider.refreshCount = 0; + provider.needsRefresh = false; provider.lastErrorTime = null; resetCount++; } diff --git a/src/utils/common.js b/src/utils/common.js index 886b9a2..7b0996e 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -325,12 +325,17 @@ export async function handleStreamRequest(res, service, model, requestBody, from // 如果底层未标记,且不跳过错误计数,则在此处标记 if (!credentialMarkedUnhealthy && !skipErrorCount && providerPoolManager && pooluuid) { - console.log(`[Provider Pool] Marking ${toProvider} as unhealthy due to stream error (status: ${status || 'unknown'})`); - // 如果是号池模式,并且请求处理失败,则标记当前使用的提供者为不健康 - providerPoolManager.markProviderUnhealthy(toProvider, { - uuid: pooluuid - }); - credentialMarkedUnhealthy = true; + // 400 报错码通常是请求参数问题,不记录为提供商错误 + if (status === 400) { + console.log(`[Provider Pool] Skipping unhealthy marking for ${toProvider} (${pooluuid}) due to status 400 (client error)`); + } else { + console.log(`[Provider Pool] Marking ${toProvider} as unhealthy due to stream error (status: ${status || 'unknown'})`); + // 如果是号池模式,并且请求处理失败,则标记当前使用的提供者为不健康 + providerPoolManager.markProviderUnhealthy(toProvider, { + uuid: pooluuid + }); + credentialMarkedUnhealthy = true; + } } else if (credentialMarkedUnhealthy) { console.log(`[Provider Pool] Credential ${pooluuid} already marked as unhealthy by lower layer, skipping duplicate marking`); } else if (skipErrorCount) { @@ -458,12 +463,17 @@ export async function handleUnaryRequest(res, service, model, requestBody, fromP // 如果底层未标记,且不跳过错误计数,则在此处标记 if (!credentialMarkedUnhealthy && !skipErrorCount && providerPoolManager && pooluuid) { - console.log(`[Provider Pool] Marking ${toProvider} as unhealthy due to unary error (status: ${status || 'unknown'})`); - // 如果是号池模式,并且请求处理失败,则标记当前使用的提供者为不健康 - providerPoolManager.markProviderUnhealthy(toProvider, { - uuid: pooluuid - }); - credentialMarkedUnhealthy = true; + // 400 报错码通常是请求参数问题,不记录为提供商错误 + if (status === 400) { + console.log(`[Provider Pool] Skipping unhealthy marking for ${toProvider} (${pooluuid}) due to status 400 (client error)`); + } else { + console.log(`[Provider Pool] Marking ${toProvider} as unhealthy due to unary error (status: ${status || 'unknown'})`); + // 如果是号池模式,并且请求处理失败,则标记当前使用的提供者为不健康 + providerPoolManager.markProviderUnhealthy(toProvider, { + uuid: pooluuid + }); + credentialMarkedUnhealthy = true; + } } else if (credentialMarkedUnhealthy) { console.log(`[Provider Pool] Credential ${pooluuid} already marked as unhealthy by lower layer, skipping duplicate marking`); } else if (skipErrorCount) { diff --git a/static/app/config-manager.js b/static/app/config-manager.js index b9e83b1..4776925 100644 --- a/static/app/config-manager.js +++ b/static/app/config-manager.js @@ -100,7 +100,7 @@ async function loadConfiguration() { if (cronNearMinutesEl) cronNearMinutesEl.value = data.CRON_NEAR_MINUTES || 1; if (cronRefreshTokenEl) cronRefreshTokenEl.checked = data.CRON_REFRESH_TOKEN || false; if (providerPoolsFilePathEl) providerPoolsFilePathEl.value = data.PROVIDER_POOLS_FILE_PATH; - if (maxErrorCountEl) maxErrorCountEl.value = data.MAX_ERROR_COUNT || 3; + if (maxErrorCountEl) maxErrorCountEl.value = data.MAX_ERROR_COUNT || 10; if (warmupTargetEl) warmupTargetEl.value = data.WARMUP_TARGET || 0; if (refreshConcurrencyPerProviderEl) refreshConcurrencyPerProviderEl.value = data.REFRESH_CONCURRENCY_PER_PROVIDER || 1; @@ -200,7 +200,7 @@ async function saveConfiguration() { config.CRON_NEAR_MINUTES = parseInt(document.getElementById('cronNearMinutes')?.value || 1); config.CRON_REFRESH_TOKEN = document.getElementById('cronRefreshToken')?.checked || false; config.PROVIDER_POOLS_FILE_PATH = document.getElementById('providerPoolsFilePath')?.value || ''; - config.MAX_ERROR_COUNT = parseInt(document.getElementById('maxErrorCount')?.value || 3); + config.MAX_ERROR_COUNT = parseInt(document.getElementById('maxErrorCount')?.value || 10); config.POOL_SIZE_LIMIT = parseInt(document.getElementById('poolSizeLimit')?.value || 0); config.WARMUP_TARGET = parseInt(document.getElementById('warmupTarget')?.value || 0); config.REFRESH_CONCURRENCY_PER_PROVIDER = parseInt(document.getElementById('refreshConcurrencyPerProvider')?.value || 1); diff --git a/static/app/i18n.js b/static/app/i18n.js index 47e9c77..5fc7730 100644 --- a/static/app/i18n.js +++ b/static/app/i18n.js @@ -294,8 +294,8 @@ const translations = { 'config.advanced.poolFilePathPlaceholder': '默认: configs/provider_pools.json', 'config.advanced.poolNote': '使用默认路径配置需添加一个空节点', 'config.advanced.maxErrorCount': '提供商最大错误次数', - 'config.advanced.maxErrorCountPlaceholder': '默认: 3', - 'config.advanced.maxErrorCountNote': '提供商连续错误达到此次数后将被标记为不健康,默认为 3 次', + 'config.advanced.maxErrorCountPlaceholder': '默认: 10', + 'config.advanced.maxErrorCountNote': '提供商连续错误达到此次数后将被标记为不健康,默认为 10 次', 'config.advanced.poolSizeLimit': '账号池轮询上限', 'config.advanced.poolSizeLimitPlaceholder': '默认: 0 (不限制)', 'config.advanced.poolSizeLimitNote': '每个提供商类型参与轮询的最大健康凭证数量,0 表示不限制,使用所有健康凭证', @@ -1007,8 +1007,8 @@ const translations = { 'config.advanced.poolFilePathPlaceholder': 'Default: configs/provider_pools.json', 'config.advanced.poolNote': 'To use default path configuration, add an empty node', 'config.advanced.maxErrorCount': 'Provider Max Error Count', - 'config.advanced.maxErrorCountPlaceholder': 'Default: 3', - 'config.advanced.maxErrorCountNote': 'Provider will be marked as unhealthy after consecutive errors reach this count, default is 3', + 'config.advanced.maxErrorCountPlaceholder': 'Default: 10', + 'config.advanced.maxErrorCountNote': 'Provider will be marked as unhealthy after consecutive errors reach this count, default is 10', 'config.advanced.poolSizeLimit': 'Pool Size Limit', 'config.advanced.poolSizeLimitPlaceholder': 'Default: 0 (no limit)', 'config.advanced.poolSizeLimitNote': 'Maximum number of healthy credentials per provider type for rotation. 0 means no limit, use all healthy credentials', diff --git a/static/components/section-config.html b/static/components/section-config.html index 4553f30..0d4f6a6 100644 --- a/static/components/section-config.html +++ b/static/components/section-config.html @@ -213,8 +213,8 @@
MAX_ERROR_COUNT