/// <summary>
        /// 强制熔断无法连通的EndPoint
        /// </summary>
        /// <param name="pathName"></param>
        /// <param name="servcieInfo"></param>
        /// <param name="breakEndPoint"></param>
        public async Task ForcedCircuitBreakEndPoint(string flowControlCfgKey, ServiceConfigureInfo configure, IPEndPoint breakEndPoint)
        {
            var addr = configure.GetEndPoints().FirstOrDefault(x => x.GetEndPoint().Equals(breakEndPoint));

            if (addr != null)
            {
                addr.BreakerTime = DateTime.Now;
            }
            await UpdateBreakerConfigure(flowControlCfgKey, configure);
        }
Example #2
0
 /// <summary>
 /// 通过配置组装熔断策略
 /// </summary>
 /// <param name="config"></param>
 /// <returns></returns>
 public IAsyncPolicy <T> BuildPolicy <T>(string key, ServiceConfigureInfo configure, IPEndPoint endpoint)
 {
     if (_lazyDefPolicy.Value.TryGetValue($"{key}{endpoint.ToString()}", out dynamic cachepolicy))
     {
         return(cachepolicy as IAsyncPolicy <T>);
     }
     else
     {
         var address = configure.GetEndPoints().FirstOrDefault(x => x.GetEndPoint().Equals(endpoint));
         //定义默认策略
         IAsyncPolicy <T> defPolicy = Policy <T> .Handle <Exception>().FallbackAsync(async(CancellationToken cancelToken) =>
         {
             //请求失败,更新配置节并进行回退
             address.ThresholdBreakeTimes += 1;
             tmpReqTime.Value.TryGetValue($"{key}{endpoint.ToString()}", out List <DateTime> time);
             time = time ?? new List <DateTime>();
             //若错误次数超过阈值或者阈值比例则触发熔断
             if (address.ThresholdBreakeTimes >= configure.DefThresholdBreakeTimes || time.Count() == 0 || (time.Count() > 0 && (double)configure.DefThresholdBreakeRatePerSec >= (double)address.ThresholdBreakeTimes / (double)time.Count(y => y >= DateTime.Now.AddSeconds(1))))
             {
                 _logger.LogError($"地址{address.GetEndPoint().ToString()}超过熔断阈值,强制熔断。详细信息{{当前IP熔断次数:{address.ThresholdBreakeTimes},成功请求次数:{time.Count()},熔断比率{(double)address.ThresholdBreakeTimes / (double)time.Count(y => y >= DateTime.Now.AddSeconds(1))}}}");
                 address.BreakerTime = DateTime.Now;
             }
             _logger.LogError($"地址{address.GetEndPoint().ToString()}请求出错,执行回退");
             return(default);
Example #3
0
        /// <summary>
        /// 检查服务断路状态
        /// </summary>
        /// <param name="pathName"></param>
        /// <param name="serviceInfo"></param>
        /// <param name="addr"></param>
        /// <returns></returns>
        public async Task <IPEndPoint> CheckCircuitByEndPoint(ServiceConfigureInfo configure, IPEndPoint clientEndPoint)
        {
            //根据配置抛弃断路状态地址
            var useAddr = configure.GetEndPoints().Where(x => x.BreakerTime == null || (x.BreakerTime != null && x.BreakerTime.Value.AddSeconds(configure.DefBreakerRetryTimeSec) <= DateTime.Now)).ToList();

            //若全部熔断
            if (!useAddr.Any())
            {
                _logger.LogError("服务被熔断,无法提供服务");
                return(null);
            }
            else
            {
                //负载均衡有效地址
                var addr = _endPointConfigure.GetServieByLoadBalane(useAddr, clientEndPoint, LoadBalanceType.IPHash, configure);
                //初始化令牌桶并判断是否限流
                _tokenBucket.InitTokenBucket(configure.DefCapacity, configure.DefRateLimit);
                if (await _tokenBucket.Grant(configure))
                {
                    return(addr);
                }
                return(null);
            }
        }