Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }