Example #1
0
 public static ILoadBalance GetLoadBalance(LoadBalanceType type, IConsumerRegister consumerRegister)
 {
     switch (type)
     {
     case LoadBalanceType.Random:
     default:
         return(new RandomLoadBalance(consumerRegister));
     }
 }
 public static string GetSlaveConnectionString(LoadBalanceType type)
 {
     if (connectConfig.DBCount == 1)
     {
         return(connectConfig.MasterConnectionString);
     }
     else
     {
         return("");
     }
 }
Example #3
0
        /*
         *  子节点调用同节点下其他业务,返回经过负载均衡器选择后的 URL
         */
        private async Task <byte[]> CallService(string clientId, RPCCallServicePayload data)
        {
            Client client = await NodeHelper.GetClient(clientId);

            if (client == null)
            {
                return(PacketHandler.MakeRPCResponse(ResponseCodeType.NodeOperationFailed));
            }

            NodeData nodeData = await NodeHelper.GetNodeData(clientId);

            if (nodeData == null)
            {
                return(PacketHandler.MakeRPCResponse(ResponseCodeType.NodeOperationFailed));
            }

            var relatedServices = new List <NodeService>();

            foreach (var currentService in nodeData.Services)
            {
                if (currentService.Key == data.Key)
                {
                    relatedServices.Add(currentService);
                }
            }

            var             keyContext       = LoadBalancer.GetKeyContext(clientId, data.Key);
            LoadBalanceType loadBalancerType = LoadBalanceType.NoLoadBalance;

            foreach (var config in client.LoadBalancerConfigurations)
            {
                if (config.Key == data.Key)
                {
                    loadBalancerType = config.Type;
                    break;
                }
            }
            NodeService serviceToUse = LoadBalancer.Lease(loadBalancerType, relatedServices, keyContext, HttpContext.Connection.RemoteIpAddress.GetHashCode(), out var hitSessionContext);

            if (serviceToUse == null) // 负载均衡器返回无可用业务备选 (业务已过期)
            {
                return(PacketHandler.MakeRPCResponse(ResponseCodeType.SvcUnavailable));
            }
            hitSessionContext.IncrementFinishedRequests();
            return(PacketHandler.MakeRPCResponse(ResponseCodeType.Ok, serviceToUse.NodeUrl));
        }
Example #4
0
        public async Task <object> ServiceMain([FromBody] ServiceRequest request)
        {
            if (!PacketHandler.ValidateServiceRequest(request))
            {
                // Bad Request 不记录日志,以防垃圾信息堆积。
                return(PacketHandler.MakeResponse(ResponseCodeType.BadRequest));
            }

            request.Key      = (request.Key ?? string.Empty).ToLower();
            request.ClientId = request.ClientId.ToLower();

            Client client = await NodeHelper.GetClient(request.ClientId);

            if (client == null)
            {
                // clientId 找不到就不记录日志。否则数据库中会充满这些未注册的 clientId 的垃圾数据。
                return(PacketHandler.MakeResponse(ResponseCodeType.SvcInvalidClientId));
            }

            Stopwatch requestWatch = null;

            if (client.LogUserRequest)
            {
                // 初始化请求计时器并开始计时处理时间
                requestWatch = new Stopwatch();
                requestWatch.Start();
            }

            // 获取并处理最终用户的 User-Agent 头部。
            string userAgentSingle = string.Empty;

            if (HttpContext.Request.Headers.TryGetValue("user-agent", out var uaHeaders) && uaHeaders.Count > 0)
            {
                // 因为 HTTP 规范允许有多个相同的头,而 UA 正常情况下只发送一个,因此只取一个值
                userAgentSingle = uaHeaders.ToArray()[0];
            }

            ServiceLog requestLog = null;

            if (client.LogUserRequest)
            {
                requestLog = new ServiceLog()
                {
                    RequestBegin = DateTime.Now,
                    Key          = request.Key,
                    RemoteIp     = HttpContext.Connection.RemoteIpAddress.ToString(),
                    RemotePort   = HttpContext.Connection.RemotePort,
                    UA           = userAgentSingle,
                    Data         = (client.LogUserPayload && request.Data != null) ? request.Data.ToString() : string.Empty,
                    ResponseCode = ResponseCodeType.Ok,
                };
            }

            NodeData nodeData = await NodeHelper.GetNodeData(request.ClientId);

            if (nodeData == null)
            {
                if (client.LogUserRequest)
                {
                    LogRequest(requestLog, request.ClientId, ResponseCodeType.SvcNotFound, requestWatch, client.LogRolling);
                }
                return(PacketHandler.MakeResponse(ResponseCodeType.SvcNotFound));
            }

            // 找到业务 Key 与其注册的所有 URL 以便负载均衡器选择
            var services = new List <NodeService>();

            foreach (NodeService svc in nodeData.Services)
            {
                if (svc.Key == request.Key && svc.Private == false)
                {
                    services.Add(svc);
                }
            }

            if (services.Count == 0) // 服务未注册(一个URL都没有注册)
            {
                if (client.LogUserRequest)
                {
                    LogRequest(requestLog, request.ClientId, ResponseCodeType.SvcNotFound, requestWatch, client.LogRolling);
                }
                return(PacketHandler.MakeResponse(ResponseCodeType.SvcNotFound));
            }

            var             keyContext       = LoadBalancer.GetKeyContext(request.ClientId, request.Key);
            LoadBalanceType loadBalancerType = LoadBalanceType.NoLoadBalance;

            foreach (var config in client.LoadBalancerConfigurations)
            {
                if (config.Key == request.Key)
                {
                    loadBalancerType = config.Type;
                    break;
                }
            }
            NodeService serviceToUse = LoadBalancer.Lease(loadBalancerType, services, keyContext, HttpContext.Connection.RemoteIpAddress.GetHashCode(), out var hitSessionContext);

            if (serviceToUse == null) // 负载均衡器返回无可用业务备选 (业务已过期)
            {
                if (client.LogUserRequest)
                {
                    LogRequest(requestLog, request.ClientId, ResponseCodeType.SvcUnavailable, requestWatch, client.LogRolling);
                }
                return(PacketHandler.MakeResponse(ResponseCodeType.SvcUnavailable));
            }

            hitSessionContext.IncrementCurrentRequests();
            try
            {
                var remoteHeaders = new Dictionary <string, string[]>();
                foreach (var header in HttpContext.Request.Headers)
                {
                    remoteHeaders.Add(header.Key.ToLower(), header.Value.ToArray());
                }
                var data = await httpClient.RequestNodeService(new Uri(serviceToUse.NodeUrl), request.Data, client.Timeout, request.ClientId, client.ClientSecret, HttpContext.Connection.RemoteIpAddress.ToString(), HttpContext.Connection.RemotePort, remoteHeaders);

                if (data == null)
                {
                    if (client.LogUserRequest)
                    {
                        LogRequest(requestLog, request.ClientId, ResponseCodeType.NodeResponseError, requestWatch, client.LogRolling);
                    }
                    hitSessionContext.IncrementFailedRequests();
                    return(PacketHandler.MakeResponse(ResponseCodeType.NodeResponseError));
                }

                if (client.LogUserRequest)
                {
                    LogRequest(requestLog, request.ClientId, ResponseCodeType.Ok, requestWatch, client.LogRolling);
                }
                return(PacketHandler.MakeResponse(ResponseCodeType.Ok, data));
            }
            catch (TaskCanceledException)
            {
                hitSessionContext.IncrementFailedRequests();
                if (client.LogUserRequest)
                {
                    LogRequest(requestLog, request.ClientId, ResponseCodeType.NodeResponseTimedout, requestWatch, client.LogRolling);
                }
                return(PacketHandler.MakeResponse(ResponseCodeType.NodeResponseTimedout));
            }
            catch
            {
                hitSessionContext.IncrementFailedRequests();
                if (client.LogUserRequest)
                {
                    LogRequest(requestLog, request.ClientId, ResponseCodeType.NodeNetworkException, requestWatch, client.LogRolling);
                }
                return(PacketHandler.MakeResponse(ResponseCodeType.NodeNetworkException));
            }
            finally
            {
                hitSessionContext.DecrementCurrentRequests();
                hitSessionContext.IncrementFinishedRequests();
            }
        }
        public IPEndPoint GetServieByLoadBalane(List <FlowControlEndPoint> lbEndPoints, IPEndPoint clientIp, LoadBalanceType type = LoadBalanceType.IPHash, ServiceConfigureInfo configure = null)
        {
            var result = default(FlowControlEndPoint);

            if (lbEndPoints != null && lbEndPoints.Any())
            {
                //若没有客户端IP则默认调用随机
                if (clientIp == null && type == LoadBalanceType.IPHash)
                {
                    type = LoadBalanceType.Random;
                }
                switch (type)
                {
                //随机
                case LoadBalanceType.Random:
                    result = lbEndPoints.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
                    break;

                //轮询
                case LoadBalanceType.Polling:
                    result = TargetIp == null?lbEndPoints.FirstOrDefault() :
                                 lbEndPoints.Any(x => x.HashSort > TargetIpSortInex) ?
                                 lbEndPoints.First(x => x.HashSort > TargetIpSortInex) :
                                 lbEndPoints.First();

                    TargetIp         = result.GetEndPoint();
                    TargetIpSortInex = result.HashSort;
                    break;

                //IP哈希
                case LoadBalanceType.IPHash:
                    result = lbEndPoints[Math.Abs(clientIp.GetHashCode()) % lbEndPoints.Count];
                    break;

                //最小连接
                case LoadBalanceType.MinConnections:
                    result = lbEndPoints.OrderBy(x => x.ConnectCount).FirstOrDefault();
                    break;
                }
            }
            if (configure != null)
            {
                configure.ChangeConnectCount(result.GetEndPoint(), true);
            }
            return(result.GetEndPoint());
        }
 public IPEndPoint GetServieByLoadBalane(List <IPEndPoint> lbEndPoints, IPEndPoint clientIp, LoadBalanceType type = LoadBalanceType.IPHash)
 {
     return(GetServieByLoadBalane(lbEndPoints.GetFlowControlEndPoints(), clientIp, type));
 }