public override UpstreamPeer Pick() { if (PeersVersion != CacheVersion) { Reset(); } if (_peers == null || _peers.Count == 0) { return(null); } if (_peers.Count == 1 && _peers[0].State == ServiceState.Up) { return(_peers[0]); } var peer = default(UpstreamPeer); int max = 0; for (int i = 0; i < _peers.Count; i++) { peer = _peers[i]; int r = 0; //被设为Down后的第一次pick if (peer.State == ServiceState.Down && peer.Range > 0) { r = -1; } else if (peer.State == ServiceState.Up && peer.Range < 0) { r = 1; } if (r != 0) { peer.Range *= -1; ReWeight(i + 1, _peers.Count, peer.Weight * r); } if (peer.State == ServiceState.Down) { continue; } if (max < peer.Range) { max = peer.Range; } } if (max == 0) { return(null); } var best = default(UpstreamPeer); int bestIdx = 0; var now = DateTime.Now; //随机算法可能多次命中无效peer,最多尝试20次 for (int tries = 0; tries < 20 && best == null; tries++) { int idx = _random.Next(max); for (int i = 0; i < _peers.Count; i++) { peer = _peers[i]; if (idx < peer.Range) { if (TriedMark?.Get(i) ?? false) { break; } if (peer.FreezedByFails(now)) { break; } best = peer; bestIdx = i; break; } } } //如果多次尝试后还是没有找到,则降级为简单选择一个可用peer if (best == null) { for (int i = 0; i < _peers.Count; i++) { peer = _peers[i]; if (TriedMark?.Get(i) ?? false) { continue; } if (peer.FreezedByFails(now)) { continue; } best = peer; bestIdx = i; } } if (best != null) { TriedMark?.Set(bestIdx, true); if (now - best.Checked > best.FailTimeout) { best.Checked = now; } } #if DEBUG var cw = _peers.Aggregate(new StringBuilder("0 - "), (a, c) => a.Append(c.Range).Append(" - ")); cw.Remove(cw.Length - 3, 3); _logger?.LogDebug($"Current weight ranges: ({cw})"); #endif return(best); }
public override UpstreamPeer Pick() { if (PeersVersion != CacheVersion) { Reset(); } if (_peers == null || _peers.Count == 0) { return(null); } if (_peers.Count == 1 && _peers[0].State == ServiceState.Up) { return(_peers[0]); } var best = default(UpstreamPeer); int bestIdx = 0; int total = 0; var now = DateTime.Now; for (int i = 0; i < _peers.Count; i++) { var peer = _peers[i]; if (peer.State == ServiceState.Down) { continue; } if (TriedMark?.Get(i) ?? false) { continue; } //请求第一次失败时,可能已经有多个请求使用了相同的peer,导致多个请求失败; //每当FailTimeout到期时,该peer仅会放行一次,导致一个请求失败(如果该peer还没恢复的话) if (peer.FreezedByFails(now)) { continue; } total += peer.EffectiveWeight; peer.CurrentWeight += peer.EffectiveWeight; if (best == null || best.CurrentWeight < peer.CurrentWeight) { best = peer; bestIdx = i; } if (peer.EffectiveWeight < peer.Weight) { peer.EffectiveWeight++; } else if (peer.EffectiveWeight > peer.Weight) { peer.EffectiveWeight--; } } if (best != null) { TriedMark?.Set(bestIdx, true); best.CurrentWeight -= total; if (now - best.Checked > best.FailTimeout) { best.Checked = now; } } #if DEBUG var cw = _peers.Aggregate(new StringBuilder(), (a, c) => a.Append(c.CurrentWeight).Append(", ")); cw.Remove(cw.Length - 2, 2); _logger?.LogDebug($"Current weights: ({cw})"); #endif return(best); }