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;
}
///
/// 发送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 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];
}
}
}