fix(provider): 增加provider.needsRefresh重置并调整最大错误次数为10
- 在重置provider健康状态时增加needsRefresh标志重置 - 将MAX_ERROR_COUNT默认值从3调整为10,提高容错性 - 忽略400状态码的错误计数,避免客户端参数问题影响provider健康状态
This commit is contained in:
parent
75e502cf10
commit
ba4ec31f9a
8 changed files with 36 additions and 24 deletions
|
|
@ -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.');
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -213,8 +213,8 @@
|
|||
|
||||
<div class="form-group pool-section">
|
||||
<label for="maxErrorCount" data-i18n="config.advanced.maxErrorCount">提供商最大错误次数</label>
|
||||
<input type="number" id="maxErrorCount" class="form-control" value="3" min="1" max="10" data-i18n-placeholder="config.advanced.maxErrorCountPlaceholder" placeholder="默认: 3">
|
||||
<small class="form-text" data-i18n="config.advanced.maxErrorCountNote">提供商连续错误达到此次数后将被标记为不健康,默认为 3 次</small>
|
||||
<input type="number" id="maxErrorCount" class="form-control" value="10" min="1" max="20" data-i18n-placeholder="config.advanced.maxErrorCountPlaceholder" placeholder="默认: 10">
|
||||
<small class="form-text" data-i18n="config.advanced.maxErrorCountNote">提供商连续错误达到此次数后将被标记为不健康,默认为 10 次</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group pool-section">
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@
|
|||
<tr>
|
||||
<td><code>MAX_ERROR_COUNT</code></td>
|
||||
<td>number</td>
|
||||
<td>3</td>
|
||||
<td>10</td>
|
||||
<td data-i18n="tutorial.main.retry.error">提供商最大错误次数,超过后标记为不健康</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
"SYSTEM_PROMPT_MODE": "overwrite",
|
||||
"REQUEST_MAX_RETRIES": 3,
|
||||
"REQUEST_BASE_DELAY": 1000,
|
||||
"MAX_ERROR_COUNT": 3,
|
||||
"MAX_ERROR_COUNT": 10,
|
||||
"PROVIDER_POOLS_FILE_PATH": "configs/provider_pools.json"
|
||||
}</code></pre>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue