fix(provider-pool-manager): 优化节点选择策略,防止序列号导致长期排挤
引入相对序列号机制,计算节点序列号相对于池中最小序列号的偏移量并封顶,避免全局自增序列号在长时间周期内对节点选择造成过度惩罚,确保公平性。同时修复重置节点时未清零序列号的问题。
This commit is contained in:
parent
a6778ce66d
commit
105bb39c1a
1 changed files with 14 additions and 3 deletions
|
|
@ -432,11 +432,19 @@ export class ProviderPoolManager {
|
||||||
// - usageCount 越多,分越大。
|
// - usageCount 越多,分越大。
|
||||||
// - lastSelectionSeq 越大(最近选过),分越大。
|
// - 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 秒
|
// usageCount * 10000: 每多用一次,权重增加 10 秒
|
||||||
// lastSelectionSeq * 1000: 即使毫秒时间相同,序列号也会让分数产生差异(增加 1 秒权重)
|
// cappedRelativeSeq * 1000: 序列号偏移只在 100 秒(10次使用)范围内波动
|
||||||
// 这样可以确保在毫秒级并发下,刚被选中的节点会立刻排到队列末尾
|
|
||||||
const baseScore = lastUsedTime + (usageCount * 10000);
|
const baseScore = lastUsedTime + (usageCount * 10000);
|
||||||
const sequenceScore = lastSelectionSeq * 1000;
|
const sequenceScore = cappedRelativeSeq * 1000;
|
||||||
|
|
||||||
return baseScore + sequenceScore;
|
return baseScore + sequenceScore;
|
||||||
}
|
}
|
||||||
|
|
@ -594,6 +602,7 @@ export class ProviderPoolManager {
|
||||||
this.providerStatus[providerType].push({
|
this.providerStatus[providerType].push({
|
||||||
config: providerConfig,
|
config: providerConfig,
|
||||||
uuid: providerConfig.uuid, // Still keep uuid at the top level for easy access
|
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.needsRefresh = false;
|
||||||
provider.config.lastErrorTime = null;
|
provider.config.lastErrorTime = null;
|
||||||
provider.config.lastErrorMessage = null;
|
provider.config.lastErrorMessage = null;
|
||||||
|
provider.config._lastSelectionSeq = 0;
|
||||||
|
|
||||||
// 更新健康检测信息
|
// 更新健康检测信息
|
||||||
if (healthCheckModel) {
|
if (healthCheckModel) {
|
||||||
|
|
@ -1163,6 +1173,7 @@ export class ProviderPoolManager {
|
||||||
if (provider) {
|
if (provider) {
|
||||||
provider.config.errorCount = 0;
|
provider.config.errorCount = 0;
|
||||||
provider.config.usageCount = 0;
|
provider.config.usageCount = 0;
|
||||||
|
provider.config._lastSelectionSeq = 0;
|
||||||
this._log('info', `Reset provider counters: ${provider.config.uuid} for type ${providerType}`);
|
this._log('info', `Reset provider counters: ${provider.config.uuid} for type ${providerType}`);
|
||||||
|
|
||||||
this._debouncedSave(providerType);
|
this._debouncedSave(providerType);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue