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.Linq;
|
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;
|
}
|
|
/// <summary>
|
/// 发送HTTP请求
|
/// </summary>
|
/// <typeparam name="TRequest"></typeparam>
|
/// <typeparam name="TResponse"></typeparam>
|
/// <param name="request"></param>
|
/// <param name="provider"></param>
|
/// <returns></returns>
|
public async Task<TResponse> SendHttpAsync<TRequest, TResponse>(
|
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<ResourceModel>();
|
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<TResponse>(httpRemoteService, builder);
|
return response;
|
}
|
|
public async Task<string> 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<string> GetUrl(string serviceName, string route)
|
{
|
var domain = await GetHealthyServiceDomain(serviceName);
|
return $"{domain}{route}";
|
}
|
|
/// <summary>
|
/// 获取健康服务域名
|
/// </summary>
|
/// <param name="serviceName"></param>
|
/// <returns></returns>
|
public async Task<string> GetHealthyServiceDomain(string serviceName)
|
{
|
var env = App.GetConfig<string>("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];
|
}
|
|
}
|
}
|