Http Polly集成

This commit is contained in:
KimiDing 2022-03-09 17:59:49 +08:00
parent ca11b2a627
commit c06e3f16b0
8 changed files with 466 additions and 2 deletions

View File

@ -722,7 +722,7 @@
Values控制器
</summary>
</member>
<member name="M:Blog.Core.Controllers.ValuesController.#ctor(Blog.Core.IServices.IBlogArticleServices,AutoMapper.IMapper,Blog.Core.IServices.IAdvertisementServices,Blog.Core.Model.Love,Blog.Core.IServices.IRoleModulePermissionServices,Blog.Core.Common.HttpContextUser.IUser,Blog.Core.IServices.IPasswordLibServices,Blog.Core.Common.WebApiClients.HttpApis.IBlogApi,Blog.Core.Common.WebApiClients.HttpApis.IDoubanApi)">
<member name="M:Blog.Core.Controllers.ValuesController.#ctor(Blog.Core.IServices.IBlogArticleServices,AutoMapper.IMapper,Blog.Core.IServices.IAdvertisementServices,Blog.Core.Model.Love,Blog.Core.IServices.IRoleModulePermissionServices,Blog.Core.Common.HttpContextUser.IUser,Blog.Core.IServices.IPasswordLibServices,Blog.Core.Common.WebApiClients.HttpApis.IBlogApi,Blog.Core.Common.WebApiClients.HttpApis.IDoubanApi,Blog.Core.Common.HttpPolly.IHttpPollyHelper)">
<summary>
ValuesController
</summary>

View File

@ -1,6 +1,7 @@
using AutoMapper;
using Blog.Core.Common;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.Common.HttpPolly;
using Blog.Core.Common.HttpRestSharp;
using Blog.Core.Common.WebApiClients.HttpApis;
using Blog.Core.EventBus;
@ -44,6 +45,7 @@ namespace Blog.Core.Controllers
private readonly IBlogApi _blogApi;
private readonly IDoubanApi _doubanApi;
readonly IBlogArticleServices _blogArticleServices;
private readonly IHttpPollyHelper _httpPollyHelper;
/// <summary>
/// ValuesController
@ -64,7 +66,8 @@ namespace Blog.Core.Controllers
, IRoleModulePermissionServices roleModulePermissionServices
, IUser user, IPasswordLibServices passwordLibServices
, IBlogApi blogApi
, IDoubanApi doubanApi)
, IDoubanApi doubanApi
, IHttpPollyHelper httpPollyHelper)
{
// 测试 Authorize 和 mapper
_mapper = mapper;
@ -82,6 +85,8 @@ namespace Blog.Core.Controllers
_blogArticleServices = blogArticleServices;
// 测试redis消息队列
_blogArticleServices = blogArticleServices;
// httpPolly
_httpPollyHelper = httpPollyHelper;
}
[HttpGet]
@ -390,6 +395,24 @@ namespace Blog.Core.Controllers
return await Task.FromResult(Appsettings.app(key));
}
#endregion
#region HttpPolly
[HttpPost]
[AllowAnonymous]
public async Task<string> HttpPollyPost()
{
var response = await _httpPollyHelper.PostAsync(HttpEnum.LocalHost, "/api/ElasticDemo/EsSearchTest", "{\"from\": 0,\"size\": 10,\"word\": \"非那雄安\"}");
return response;
}
[HttpGet]
[AllowAnonymous]
public async Task<string> HttpPollyGet()
{
return await _httpPollyHelper.GetAsync(HttpEnum.LocalHost, "/api/ElasticDemo/GetDetailInfo?esid=3130&esindex=chinacodex");
}
#endregion
}
public class ClaimDto
{

View File

@ -97,6 +97,7 @@ namespace Blog.Core
services.AddDistributedMemoryCache();
services.AddSession();
services.AddHttpPollySetup();
services.AddControllers(o =>
{

View File

@ -0,0 +1,354 @@
using Blog.Core.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Common.HttpPolly
{
public class HttpPollyHelper : IHttpPollyHelper
{
private readonly IHttpClientFactory _clientFactory;
public HttpPollyHelper(IHttpClientFactory httpClientFactory)
{
_clientFactory = httpClientFactory;
}
public async Task<T> PostAsync<T, R>(HttpEnum httpEnum, string url, R request, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<T> PostAsync<T>(HttpEnum httpEnum, string url, string request, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<string> PostAsync<R>(HttpEnum httpEnum, string url, R request, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<string> PostAsync(HttpEnum httpEnum, string url, string request, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<T> GetAsync<T>(HttpEnum httpEnum, string url, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var response = await client.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<string> GetAsync(HttpEnum httpEnum, string url, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var response = await client.GetAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync(); ;
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<T> PutAsync<T, R>(HttpEnum httpEnum, string url, R request, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<T> PutAsync<T>(HttpEnum httpEnum, string url, string request, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, stringContent);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
public async Task<T> DeleteAsync<T>(HttpEnum httpEnum, string url, Dictionary<string, string> headers = null)
{
try
{
var client = _clientFactory.CreateClient(httpEnum.ToString());
if (headers != null)
{
foreach (var header in headers)
{
if (!client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
}
}
var response = await client.DeleteAsync(url);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception($"Http Error StatusCode:{response.StatusCode}");
}
}
catch (Exception)
{
throw;
}
}
}
}

View File

@ -0,0 +1,19 @@
using Blog.Core.Model;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Blog.Core.Common.HttpPolly
{
public interface IHttpPollyHelper
{
Task<T> PostAsync<T, R>(HttpEnum httpEnum, string url, R request, Dictionary<string, string> headers = null);
Task<T> PostAsync<T>(HttpEnum httpEnum, string url, string request, Dictionary<string, string> headers = null);
Task<string> PostAsync(HttpEnum httpEnum, string url, string request, Dictionary<string, string> headers = null);
Task<string> PostAsync<R>(HttpEnum httpEnum, string url, R request, Dictionary<string, string> headers = null);
Task<T> GetAsync<T>(HttpEnum httpEnum, string url, Dictionary<string, string> headers = null);
Task<string> GetAsync(HttpEnum httpEnum, string url, Dictionary<string, string> headers = null);
Task<T> PutAsync<T, R>(HttpEnum httpEnum, string url, R request, Dictionary<string, string> headers = null);
Task<T> PutAsync<T>(HttpEnum httpEnum, string url, string request, Dictionary<string, string> headers = null);
Task<T> DeleteAsync<T>(HttpEnum httpEnum, string url, Dictionary<string, string> headers = null);
}
}

View File

@ -15,6 +15,7 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.14" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="5.0.0-preview.2.20167.3" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.2.20160.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />

View File

@ -0,0 +1,56 @@
using Blog.Core.Common.HttpPolly;
using Blog.Core.Model;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;
using Polly.Timeout;
using System;
using System.Net.Http;
namespace Blog.Core.Extensions
{
/// <summary>
/// Cors 启动服务
/// </summary>
public static class HttpPollySetup
{
public static void AddHttpPollySetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
#region Polly策略
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>() // 若超时则抛出此异常
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
});
// 为每个重试定义超时策略
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10);
#endregion
services.AddHttpClient(HttpEnum.Common.ToString(), c =>
{
c.DefaultRequestHeaders.Add("Accept", "application/json");
})
.AddPolicyHandler(retryPolicy)
// 将超时策略放在重试策略之内,每次重试会应用此超时策略
.AddPolicyHandler(timeoutPolicy);
services.AddHttpClient(HttpEnum.LocalHost.ToString(), c =>
{
c.BaseAddress = new Uri("http://www.localhost.com");
c.DefaultRequestHeaders.Add("Accept", "application/json");
})
.AddPolicyHandler(retryPolicy)
// 将超时策略放在重试策略之内,每次重试会应用此超时策略
.AddPolicyHandler(timeoutPolicy);
services.AddSingleton<IHttpPollyHelper, HttpPollyHelper>();
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace Blog.Core.Model
{
public enum HttpEnum
{
Common,
LocalHost
}
}