From 105bb39c1a841f64fd1d206191921cda5cb0f042 Mon Sep 17 00:00:00 2001 From: hex2077 Date: Sat, 14 Feb 2026 23:20:39 +0800 Subject: [PATCH] =?UTF-8?q?fix(provider-pool-manager):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=8A=82=E7=82=B9=E9=80=89=E6=8B=A9=E7=AD=96=E7=95=A5?= =?UTF-8?q?=EF=BC=8C=E9=98=B2=E6=AD=A2=E5=BA=8F=E5=88=97=E5=8F=B7=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E9=95=BF=E6=9C=9F=E6=8E=92=E6=8C=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引入相对序列号机制,计算节点序列号相对于池中最小序列号的偏移量并封顶,避免全局自增序列号在长时间周期内对节点选择造成过度惩罚,确保公平性。同时修复重置节点时未清零序列号的问题。 --- src/providers/provider-pool-manager.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/providers/provider-pool-manager.js b/src/providers/provider-pool-manager.js index cfa7df8..25ec8d5 100644 --- a/src/providers/provider-pool-manager.js +++ b/src/providers/provider-pool-manager.js @@ -432,11 +432,19 @@ export class ProviderPoolManager { // - usageCount 越多,分越大。 // - lastSelectionSeq 越大(最近选过),分越大。 + // --- 策略优化:相对序列号 --- + // 为了防止全局自增序列号导致的“老节点排挤新节点”或“重置节点排挤未重置节点” + // 我们计算节点序列号相对于当前池中最小序列号的偏移量,并对该偏移量进行封顶处理。 + // 这样序列号只在打破“同一毫秒”的平局时起作用,而不会成为跨越长时间周期的惩罚。 + const pool = this.providerStatus[providerStatus.type] || []; + const minSeqInPool = Math.min(...pool.map(p => p.config._lastSelectionSeq || 0)); + const relativeSeq = Math.max(0, lastSelectionSeq - minSeqInPool); + const cappedRelativeSeq = Math.min(relativeSeq, 100); // 封顶偏移量,确保它只影响微观排序 + // usageCount * 10000: 每多用一次,权重增加 10 秒 - // lastSelectionSeq * 1000: 即使毫秒时间相同,序列号也会让分数产生差异(增加 1 秒权重) - // 这样可以确保在毫秒级并发下,刚被选中的节点会立刻排到队列末尾 + // cappedRelativeSeq * 1000: 序列号偏移只在 100 秒(10次使用)范围内波动 const baseScore = lastUsedTime + (usageCount * 10000); - const sequenceScore = lastSelectionSeq * 1000; + const sequenceScore = cappedRelativeSeq * 1000; return baseScore + sequenceScore; } @@ -594,6 +602,7 @@ export class ProviderPoolManager { this.providerStatus[providerType].push({ config: providerConfig, uuid: providerConfig.uuid, // Still keep uuid at the top level for easy access + type: providerType, // 保存 providerType 引用 }); }); } @@ -1097,6 +1106,7 @@ export class ProviderPoolManager { provider.config.needsRefresh = false; provider.config.lastErrorTime = null; provider.config.lastErrorMessage = null; + provider.config._lastSelectionSeq = 0; // 更新健康检测信息 if (healthCheckModel) { @@ -1163,6 +1173,7 @@ export class ProviderPoolManager { if (provider) { provider.config.errorCount = 0; provider.config.usageCount = 0; + provider.config._lastSelectionSeq = 0; this._log('info', `Reset provider counters: ${provider.config.uuid} for type ${providerType}`); this._debouncedSave(providerType);