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); } }
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); }
/// <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); }
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"); }
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); } }
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); } }
/// <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}"); }
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)); }
/// <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}接口请求异常"); }
/// <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}请求出错"); }