Пример #1
0
 /// <summary>
 /// 通过代理类发送消息到远程服务器
 /// </summary>
 /// <typeparam name="TIn"></typeparam>
 /// <typeparam name="TOut"></typeparam>
 /// <param name="input"></param>
 /// <param name="serviceName"></param>
 /// <param name="FlowControlCfgKey"></param>
 /// <param name="pathName"></param>
 /// <returns></returns>
 public async Task<TOut> SendAsync<TIn, TOut>(TIn input, string serviceName, string flowControlCfgKey, string pathName) where TOut : class
 {
     try
     {
         var configure = await _configureManager.GetBreakerConfigure(flowControlCfgKey);
         //流量控制
         var ipendpoint = await _flowControlCenter.GetFlowControlEndPointByServicePath(serviceName, configure, _customerInfo.Ip);
         if (ipendpoint != null)
         {
             var channelKey = await _clientProvider.CreateClient(ipendpoint);
             if (channelKey != null)
             {
                 return await _clientProvider.SendMessage<TOut>(channelKey, ipendpoint, flowControlCfgKey, configure, serviceName, pathName, input);
             }
             else
             {
                 _oxygenLogger.LogError($"远程调用通道创建失败:{ipendpoint.ToString()}");
                 //强制熔断当前节点
                 await _configureManager.ForcedCircuitBreakEndPoint(flowControlCfgKey, configure, ipendpoint);
             }
         }
     }
     catch (Exception e)
     {
         _oxygenLogger.LogError($"远程调用失败:{e.Message},堆栈跟踪:{e.StackTrace.ToString()}");
     }
     return await Task.FromResult(default(TOut));
 }
Пример #2
0
 /// <summary>
 /// 从tcp管道接受消息
 /// </summary>
 /// <param name="context"></param>
 /// <param name="message"></param>
 public override void ChannelRead(IChannelHandlerContext context, object message)
 {
     try
     {
         if (message is RpcGlobalMessageBase <object> )
         {
             _hander?.Invoke((RpcGlobalMessageBase <object>)message);
         }
     }
     catch (Exception e)
     {
         _logger.LogError("客户端回调处理异常: " + e.Message);
     }
 }
Пример #3
0
        /// <summary>
        /// 从tcp管道接受消息
        /// </summary>
        /// <param name="context"></param>
        /// <param name="message"></param>
        public override async void ChannelRead(IChannelHandlerContext context, object message)
        {
            try
            {
                if (message is RpcGlobalMessageBase <object> )
                {
                    var localHanderResult = await _localProxyGenerator.Invoke((RpcGlobalMessageBase <object>) message);

                    if (localHanderResult != null)
                    {
                        await context.WriteAsync(localHanderResult);
                    }
                }
            }
            catch (Exception e)
            {
                _logger.LogError("服务端消息处理异常: " + e.Message);
            }
        }
Пример #4
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);
Пример #5
0
 /// <summary>
 /// 序列化
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="input"></param>
 /// <returns></returns>
 public byte[] Serializes <T>(T input)
 {
     if (input == null)
     {
         return(default(byte[]));
     }
     try
     {
         return(MessagePackSerializer.Serialize(input));
     }
     catch (Exception e)
     {
         _logger.LogError($"序列化对象失败:{e.Message}");
     }
     return(default(byte[]));
 }
Пример #6
0
 /// <summary>
 /// 通过强类型创建代理
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <returns></returns>
 public async Task <T> CreateProxy <T>() where T : class
 {
     if (_container.TryResolve(typeof(T), out var instance))
     {
         return(instance as T);
     }
     else
     {
         var className = $"{typeof(T).Name.Substring(1, typeof(T).Name.Length - 1)}_ProxyClient";
         var type      = GetProxtClient(className);
         if (type != null)
         {
             return(Activator.CreateInstance(type) as T);
         }
         else
         {
             _oxygenLogger.LogError($"未找到远程代理实例:{typeof(T).Name}");
         }
     }
     return(await Task.FromResult(default(T)));
 }
Пример #7
0
        /// <summary>
        /// 根据服务名返回IP地址
        /// </summary>
        /// <param name="serviceName"></param>
        /// <param name="flowControlCfgKey"></param>
        /// <param name="clientIp"></param>
        /// <returns></returns>
        public async Task <IPEndPoint> GetFlowControlEndPointByServicePath(string serviceName, ServiceConfigureInfo configure, IPEndPoint clientIp)
        {
            //根据服务返回健康地址
            var healthNode = await _registerCenter.GetServieByName(serviceName);

            if (healthNode != null && healthNode.Any())
            {
                if (configure != null)
                {
                    //更新健康节点和缓存同步
                    configure.ReflushConfigureEndPoint(healthNode);
                    //若配置流控,则进行熔断和限流检测
                    var point = await _breaker.CheckCircuitByEndPoint(configure, clientIp);

                    if (point != null)
                    {
                        //将有效地址的熔断数据清空
                        configure.CleanBreakTimes();
                        return(point);
                    }
                }
                else
                {
                    //如果当前服务并未配置流控,则直接负载均衡返回节点
                    return(_endPointConfigure.GetServieByLoadBalane(healthNode, clientIp, LoadBalanceType.IPHash));
                }
            }
            else
            {
                //删除所有地址并同步
                if (configure != null)
                {
                    configure.RemoveAllNode();
                }
                _logger.LogError($"没有找到健康的服务节点:{serviceName}");
            }
            return(null);
        }
Пример #8
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);
            }
        }
Пример #9
0
 /// <summary>
 /// 消息分发处理
 /// </summary>
 /// <param name="message"></param>
 /// <returns></returns>
 public async Task <RpcGlobalMessageBase <object> > Invoke(RpcGlobalMessageBase <object> message)
 {
     if (message == null)
     {
         _logger.LogError($"订阅者消息分发不能为空消息");
         return(default);