public void Get_LoadBalancer_Test()
        {
            var loadBalancer1 = _loadBalancerHouse.Get("micro.addresstable.service1");

            Assert.Equal(LoadBalancerConsts.NoLoadBalancer, loadBalancer1.BalancerType);

            var loadBalancer2 = _loadBalancerHouse.Get("micro.addresstable.service2");

            Assert.Equal(LoadBalancerConsts.Random, loadBalancer2.BalancerType);

            var loadBalancer3 = _loadBalancerHouse.Get("micro.addresstable.service3");

            Assert.Equal(LoadBalancerConsts.WeightRoundRobin, loadBalancer3.BalancerType);

            var loadBalancer4 = _loadBalancerHouse.Get("micro.addresstable.service4");

            Assert.Equal(LoadBalancerConsts.RoundRobin, loadBalancer4.BalancerType);
        }
        public async Task Invoke(HttpContext httpContext)
        {
            var downstreamRoute = httpContext.Items.DownstreamRoute();

            var internalConfiguration = httpContext.Items.IInternalConfiguration();

            var loadBalancer = _loadBalancerHouse.Get(downstreamRoute, internalConfiguration.ServiceProviderConfiguration);

            if (loadBalancer.IsError)
            {
                Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
                httpContext.Items.UpsertErrors(loadBalancer.Errors);
                return;
            }

            var hostAndPort = await loadBalancer.Data.Lease(httpContext);

            if (hostAndPort.IsError)
            {
                Logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
                httpContext.Items.UpsertErrors(hostAndPort.Errors);
                return;
            }

            var downstreamRequest = httpContext.Items.DownstreamRequest();

            //todo check downstreamRequest is ok
            downstreamRequest.Host = hostAndPort.Data.DownstreamHost;

            if (hostAndPort.Data.DownstreamPort > 0)
            {
                downstreamRequest.Port = hostAndPort.Data.DownstreamPort;
            }

            if (!string.IsNullOrEmpty(hostAndPort.Data.Scheme))
            {
                downstreamRequest.Scheme = hostAndPort.Data.Scheme;
            }

            try
            {
                await _next.Invoke(httpContext);
            }
            catch (Exception)
            {
                Logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
                throw;
            }
            finally
            {
                loadBalancer.Data.Release(hostAndPort.Data);
            }
        }
Пример #3
0
        public async Task NoLoadBalancer_First_Last_Test()
        {
            var loadBalancer1 = _loadBalancerHouse.Get("micro.addresstable.service1");

            Assert.Equal(LoadBalancerConsts.NoLoadBalancer, loadBalancer1.BalancerType);
            var service1 = await loadBalancer1.Lease();

            Assert.Equal("1-2", service1.Id);
            var service2 = await loadBalancer1.Lease();

            Assert.Equal("1-2", service2.Id);
            var loadBalancer2 = _loadBalancerHouse.Get("micro.addresstable.service1");

            Assert.Equal(loadBalancer1, loadBalancer2);
        }
Пример #4
0
        /// <summary>
        /// get config http url
        /// </summary>
        /// <returns></returns>
        public string GetConfigService()
        {
            string configHttpUrl = string.Empty;

            if (_setting.UseServiceDiscovery && _loadBalancerHouse != null)
            {
                var _load       = _loadBalancerHouse.Get(_setting.ServiceName, "RoundRobin").GetAwaiter().GetResult();
                var HostAndPort = _load.Lease().GetAwaiter().GetResult();
                configHttpUrl = $"{HostAndPort.ToUri()}";
            }
            else
            {
                configHttpUrl = _setting.ServerUrl;
            }
            return(configHttpUrl);
        }
Пример #5
0
        public async Task Invoke(HttpContext context)
        {
            _logger.LogDebug("started calling load balancing middleware");

            var loadBalancer = _loadBalancerHouse.Get(DownstreamRoute.ReRoute.ReRouteKey);

            if (loadBalancer.IsError)
            {
                SetPipelineError(loadBalancer.Errors);
                return;
            }

            var hostAndPort = await loadBalancer.Data.Lease();

            if (hostAndPort.IsError)
            {
                SetPipelineError(hostAndPort.Errors);
                return;
            }

            var uriBuilder = new UriBuilder(DownstreamRequest.RequestUri);

            uriBuilder.Host = hostAndPort.Data.DownstreamHost;
            if (hostAndPort.Data.DownstreamPort > 0)
            {
                uriBuilder.Port = hostAndPort.Data.DownstreamPort;
            }
            DownstreamRequest.RequestUri = uriBuilder.Uri;

            _logger.LogDebug("calling next middleware");

            try
            {
                await _next.Invoke(context);

                loadBalancer.Data.Release(hostAndPort.Data);
            }
            catch (Exception)
            {
                loadBalancer.Data.Release(hostAndPort.Data);

                _logger.LogDebug("error calling next middleware, exception will be thrown to global handler");
                throw;
            }

            _logger.LogDebug("succesfully called next middleware");
        }
Пример #6
0
        public async Task Invoke(DownstreamContext context)
        {
            var loadBalancer = await _loadBalancerHouse.Get(context.DownstreamReRoute, context.Configuration.ServiceProviderConfiguration);

            if (loadBalancer.IsError)
            {
                Logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
                SetPipelineError(context, loadBalancer.Errors);
                return;
            }

            var hostAndPort = await loadBalancer.Data.Lease(context);

            if (hostAndPort.IsError)
            {
                Logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
                SetPipelineError(context, hostAndPort.Errors);
                return;
            }

            context.DownstreamRequest.Host = hostAndPort.Data.DownstreamHost;

            if (hostAndPort.Data.DownstreamPort > 0)
            {
                context.DownstreamRequest.Port = hostAndPort.Data.DownstreamPort;
            }

            if (!string.IsNullOrEmpty(hostAndPort.Data.Scheme))
            {
                context.DownstreamRequest.Scheme = hostAndPort.Data.Scheme;
            }

            try
            {
                await _next.Invoke(context);
            }
            catch (Exception)
            {
                Logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
                throw;
            }
            finally
            {
                loadBalancer.Data.Release(hostAndPort.Data);
            }
        }
Пример #7
0
        public async Task Invoke(HttpContext context)
        {
            var loadBalancer = await _loadBalancerHouse.Get(DownstreamRoute.ReRoute, ServiceProviderConfiguration);

            if (loadBalancer.IsError)
            {
                _logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
                SetPipelineError(loadBalancer.Errors);
                return;
            }

            var hostAndPort = await loadBalancer.Data.Lease();

            if (hostAndPort.IsError)
            {
                _logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
                SetPipelineError(hostAndPort.Errors);
                return;
            }

            var uriBuilder = new UriBuilder(DownstreamRequest.RequestUri);

            uriBuilder.Host = hostAndPort.Data.DownstreamHost;

            if (hostAndPort.Data.DownstreamPort > 0)
            {
                uriBuilder.Port = hostAndPort.Data.DownstreamPort;
            }

            DownstreamRequest.RequestUri = uriBuilder.Uri;

            try
            {
                await _next.Invoke(context);
            }
            catch (Exception)
            {
                _logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
                throw;
            }
            finally
            {
                loadBalancer.Data.Release(hostAndPort.Data);
            }
        }
Пример #8
0
        /// <summary>
        /// 获取负载Api接口地址
        /// </summary>
        /// <param name="serviceName"></param>
        /// <param name="webApiPath"></param>
        /// <param name="scheme"></param>
        /// <returns></returns>
        private string GetApiUrl(string serviceName, string webApiPath, string scheme)
        {
            var _load = _loadBalancerHouse.Get(serviceName).GetAwaiter().GetResult();

            if (_load == null)
            {
                throw new ArgumentNullException(nameof(_load));
            }
            var HostAndPort = _load.Lease().GetAwaiter().GetResult();

            if (HostAndPort == null)
            {
                throw new ArgumentNullException(nameof(HostAndPort));
            }
            string baseAddress = $"{scheme}://{HostAndPort.ToString()}/";

            webApiPath = webApiPath.TrimStart('/');

            return($"{baseAddress}{webApiPath}");
        }
Пример #9
0
        private string AssembleQueryConfigUrl()
        {
            string url = string.Empty;

            if (_setting.UseServiceDiscovery && _loadBalancerHouse != null)
            {
                var _load       = _loadBalancerHouse.Get(_setting.ServiceName, "RoundRobin").GetAwaiter().GetResult();
                var HostAndPort = _load.Lease().GetAwaiter().GetResult();
                url = $"{HostAndPort.ToUri()}";
            }
            else
            {
                url = _setting.ServerUrl;
            }
            string appId  = _setting.AppId;
            string secret = _setting.AppSercet;

            var uri   = $"{url.TrimEnd('/')}/configs/{_setting.AppId}/{_setting.NamespaceName}";
            var query = $"version={_config.Version}";
            var sign  = $"appId={appId}&appSecret={secret}&namespaceName={_setting.NamespaceName}";

            return($"{uri}?{query}&sign=" + SecureHelper.SHA256(sign));
        }
Пример #10
0
        /// <summary>
        /// get 请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serviceName"></param>
        /// <param name="webApiPath"></param>
        /// <param name="scheme"></param>
        /// <param name="customHeaders"></param>
        /// <param name="MediaType"></param>
        /// <param name="isBuried"></param>
        /// <returns></returns>
        public T GetWebApi <T>(string serviceName, string webApiPath,
                               string scheme = "http",
                               Dictionary <string, string> customHeaders = null,
                               string MediaType = "application/json",
                               bool isTrace     = false)
        {
            #region 负载寻址
            var _load = _loadBalancerHouse.Get(serviceName).GetAwaiter().GetResult();
            if (_load == null)
            {
                throw new ArgumentNullException(nameof(_load));
            }
            var HostAndPort = _load.Lease().GetAwaiter().GetResult();
            if (HostAndPort == null)
            {
                throw new ArgumentNullException(nameof(HostAndPort));
            }
            string baseAddress = $"{scheme}://{HostAndPort.ToString()}/";
            webApiPath = webApiPath.TrimStart('/');
            #endregion

            #region  游请求头处理
            if (isTrace)
            {
                // 请求头下发,埋点请求头
                if (customHeaders == null)
                {
                    customHeaders = new Dictionary <string, string>();
                }
                var downStreamHeaders = _tracer.DownTraceHeaders(_httpContextAccessor.HttpContext);
                // 合并键值
                customHeaders = customHeaders.Concat(downStreamHeaders).ToDictionary(k => k.Key, v => v.Value);
            }
            #endregion

            #region 请求埋点
            var traceLog = new TraceLogs()
            {
                ApiUri      = $"{baseAddress}{webApiPath}",
                ContextType = MediaType,
                StartTime   = DateTime.Now,
            };
            if (isTrace)
            {
                _tracer.AddHeadersToTracer <TraceLogs>(_httpContextAccessor.HttpContext, traceLog);
                if (customHeaders.TryGetValue(TracerKeys.TraceSeq, out string value))
                {
                    traceLog.ParentSeq = value;
                }
            }
            #endregion

            #region http 请求
            var request = new HttpRequestMessage
            {
                RequestUri = new Uri($"{baseAddress}{webApiPath}"),
                Method     = HttpMethod.Get
            };
            request.Headers.Clear();
            request.Headers.Accept.Clear();
            if (customHeaders != null)
            {
                foreach (KeyValuePair <string, string> customHeader in customHeaders)
                {
                    request.Headers.Add(customHeader.Key, customHeader.Value);
                }
            }
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType));
            traceLog.Request = request.RequestUri.Query;
            try
            {
                var httpResponseMessage = _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult();
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    traceLog.IsSuccess   = true;
                    traceLog.IsException = false;
                    if (typeof(T) == typeof(byte[]))
                    {
                        return((T)Convert.ChangeType(httpResponseMessage.Content.ReadAsByteArrayAsync().Result, typeof(T)));
                    }
                    if (typeof(T) == typeof(Stream))
                    {
                        return((T)Convert.ChangeType(httpResponseMessage.Content.ReadAsStreamAsync().Result, typeof(T)));;
                    }
                    if (typeof(T) == typeof(String))
                    {
                        var result = httpResponseMessage.Content.ReadAsStringAsync().Result;
                        traceLog.Response = result;
                        return((T)Convert.ChangeType(result, typeof(T)));
                    }
                    else
                    {
                        var result = httpResponseMessage.Content.ReadAsStringAsync().Result;
                        traceLog.Response = result;
                        return(_jsonHelper.DeserializeObject <T>(result));
                    }
                }
            }
            catch (Exception ex)
            {
                traceLog.IsException = true;
                _logger.LogError(ex, $"服务{serviceName},路径{webApiPath}接口请求异常");
            }
            finally
            {
                if (isTrace)
                {
                    traceLog.EndTime    = DateTime.Now;
                    traceLog.TimeLength = Math.Round((traceLog.EndTime - traceLog.StartTime).TotalMilliseconds, 4);
                    _tracer.PublishAsync <TraceLogs>(traceLog).GetAwaiter();
                }
            }
            #endregion

            throw new Exception($"服务{serviceName},路径{webApiPath}接口请求异常");
        }
Пример #11
0
        /// <summary>
        /// get 请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="serviceName"></param>
        /// <param name="webApiPath"></param>
        /// <param name="scheme"></param>
        /// <param name="customHeaders"></param>
        /// <param name="MediaType"></param>
        /// <param name="isBuried"></param>
        /// <returns></returns>
        public T GetWebApi <T>(string serviceName, string webApiPath,
                               string scheme = "http",
                               Dictionary <string, string> customHeaders = null,
                               string MediaType = "application/json",
                               bool isBuried    = false)
        {
            #region 负载寻址
            var _load = _loadBalancerHouse.Get(serviceName).GetAwaiter().GetResult();
            if (_load == null)
            {
                throw new ArgumentNullException(nameof(_load));
            }
            var HostAndPort = _load.Lease().GetAwaiter().GetResult();
            if (HostAndPort == null)
            {
                throw new ArgumentNullException(nameof(HostAndPort));
            }
            string baseAddress = $"{scheme}://{HostAndPort.ToString()}";
            webApiPath = webApiPath.StartsWith("/") ? webApiPath : "/" + webApiPath;
            #endregion

            #region  游请求头处理
            // 请求头下发,埋点请求头
            if (customHeaders == null)
            {
                customHeaders = new Dictionary <string, string>();
            }
            var downStreamHeaders = _buriedContext.DownStreamHeaders();
            // 合并键值
            customHeaders = customHeaders.Concat(downStreamHeaders).ToDictionary(k => k.Key, v => v.Value);
            #endregion

            #region 请求埋点
            if (isBuried) // 埋点
            {
                _buriedContext.PublishAsync(new
                {
                    ApiType          = 1,
                    ApiUri           = string.Concat(baseAddress, "/", webApiPath),
                    BussinessSuccess = 0,
                    CalledResult     = 0,
                    InputParams      = webApiPath
                }).GetAwaiter();
            }
            #endregion

            #region http 请求
            var request = new HttpRequestMessage
            {
                RequestUri = new Uri($"{baseAddress}{webApiPath}"),
                Method     = HttpMethod.Get
            };
            request.Headers.Clear();
            request.Headers.Accept.Clear();
            if (customHeaders != null)
            {
                foreach (KeyValuePair <string, string> customHeader in customHeaders)
                {
                    request.Headers.Add(customHeader.Key, customHeader.Value);
                }
            }
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaType));
            var httpResponseMessage = _httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult();
            if (httpResponseMessage.StatusCode == HttpStatusCode.OK || httpResponseMessage.StatusCode == HttpStatusCode.NotModified)
            {
                var content = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();

                #region 请求埋点
                if (isBuried) // 埋点
                {
                    _buriedContext.PublishAsync(new
                    {
                        ApiType          = 1,
                        ApiUri           = string.Concat(baseAddress, "/", webApiPath),
                        BussinessSuccess = 0,
                        CalledResult     = 0,
                        InputParams      = webApiPath,
                        OutputParams     = content,
                    }).GetAwaiter();
                }
                #endregion

                return(_jsonHelper.DeserializeObject <T>(content));
            }
            #endregion

            throw new Exception($"服务{serviceName},路径{webApiPath}请求出错");
        }