/// <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); }
/// <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); } }