using Azure; using Consul; using Furion; using Furion.FriendlyException; using Furion.HttpRemote; using Microsoft.Extensions.Caching.Distributed; using System; using System.Collections.Generic; using System.ComponentModel.Design; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core { public class ResourceHttpUtils { private readonly IDistributedCache distributedCache; private readonly IHttpRemoteService httpRemoteService; private readonly IConsulClient consulClient; public ResourceHttpUtils( IDistributedCache distributedCache, IHttpRemoteService httpRemoteService, IConsulClient consulClient) { this.distributedCache = distributedCache; this.httpRemoteService = httpRemoteService; this.consulClient = consulClient; } /// /// 发送HTTP请求 /// /// /// /// /// /// public async Task SendHttpAsync( TRequest request, IResourceHttpProvider provider = null) where TRequest : class, new() { var requestTypeFullName = typeof(TRequest).FullName; var jsonResourceModels = await distributedCache.GetStringAsync($"ResourceModel|{requestTypeFullName}"); var resource = jsonResourceModels.JsonTo(); var url = await GetUrl(resource.ServiceName, resource.Route); var builder = HttpRequestBuilder.Create(resource.GetHttpMethod(), url); if (resource.Method == EnumResourceMethod.Get) builder = builder.WithQueryParameters(request); else builder = builder.SetJsonContent(request); provider = provider ?? new DefaultResourceHttpProvider(); builder = provider.AddAuthentication(builder); var response = await provider.SendAsAsync(httpRemoteService, builder); return response; } public async Task SendHttpAsync(Resource resource, string request, IResourceHttpProvider provider = null) { var url = await GetUrl(resource.ServiceName, resource.Route); var builder = HttpRequestBuilder.Create(resource.GetHttpMethod(), url); if (resource.Method == EnumResourceMethod.Get) builder = builder.WithQueryParameters(request); else builder = builder.SetJsonContent(request); provider = provider ?? new DefaultResourceHttpProvider(); builder = provider.AddAuthentication(builder); var response = await provider.SendAsStringAsync(httpRemoteService, builder); return response; } public async Task SendHttpAsync(EnumResourceService service, HttpMethod method, string route, string request, IResourceHttpProvider provider = null) { var serviceName = service.GetCustomAttribute().ServiceName; var url = await GetUrl(serviceName, route); var builder = HttpRequestBuilder.Create(method, url); if (method == HttpMethod.Get) builder = builder.WithQueryParameters(request); else builder = builder.SetJsonContent(request); provider = provider ?? new DefaultResourceHttpProvider(); builder = provider.AddAuthentication(builder); var response = await provider.SendAsStringAsync(httpRemoteService, builder); return response; } public async Task GetUrl(string serviceName, string route) { var domain = await GetHealthyServiceDomain(serviceName); return $"{domain}{route}"; } /// /// 获取健康服务域名 /// /// /// public async Task GetHealthyServiceDomain(string serviceName) { var env = App.GetConfig("Environment"); serviceName = $"{env}_{serviceName}"; var queryResult = await consulClient.Health.Service(serviceName, null, true); if (queryResult.StatusCode != System.Net.HttpStatusCode.OK) throw Oops.Oh(EnumErrorCodeType.s404, $"微服务{serviceName}"); var domains = queryResult.Response .Select(s => $"http://{s.Service.Address}:{s.Service.Port}") .ToList(); if (domains.IsNull()) throw Oops.Oh(EnumErrorCodeType.s404, $"微服务{serviceName}"); // 轮询选择实例 int randomIndex = new Random().Next(domains.Count); return domains[randomIndex]; } } }