一、介紹
在IServiceCollection調用AddHttpClient注冊IHttpClientFactory服務,調用AddHttpMessageHandler以生成出站請求中間件管道。 每個處理程序都可以在出站請求前后執行工作。通過Polly 的處理程序,以表達策略處理重試、斷路器、超時、隔離和回退。
二、使用http請求
1.配置注冊
var host = new HostBuilder() .ConfigureServices((context, services) => { services.AddHttpClient(); services.AddHostedService<MyHostedService>(); }) .UseConsoleLifetime() .Build();
2.請求的后台服務
public Task StartAsync(CancellationToken cancellationToken) { return Task.Run(async () => { var request = new HttpRequestMessage(HttpMethod.Post, "http://www.baidu.com"); request.Headers.Add("Accept", "application/json");//設置請求頭 request.Properties.Add("id","123");//設置請求參數 var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); string result = null; if (response.IsSuccessStatusCode) { result = await response.Content.ReadAsStringAsync(); } }); }
3.執行時控制台輸入日志
二、以客戶端的方式使用
在客戶端中配置,默認請求Url地址和默認的header。
public class HaosRequestService { public HttpClient Client { get; } public HaosRequestService(HttpClient client) { //配置默認值 client.BaseAddress = new Uri("http://www.baidu.com/"); client.DefaultRequestHeaders.Add("Accept","application/json"); Client = client; } /// <summary> /// 封裝常用方法 /// </summary> /// <param name="key"></param> /// <returns></returns> public async Task<string> SeachAsync(string key) { var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string,string>("w","關鍵字"), }); var response = await Client.PostAsync("/s",content); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } }
在IServiceCollection中注冊
var host = new HostBuilder() .ConfigureServices((context, services) => { services.AddHttpClient<HaosRequestService>(); services.AddHostedService<MyHostedService>(); })
三、處理出站 HTTP 請求
IHttpClientFactory 可以為客戶端定義處理程,支持注冊和鏈接多個處理程序。要創建處理程序,先定義一個繼承 DelegatingHandler
的類。 重寫 SendAsync
方法,在將請求傳遞至管道中的下一個處理程序之前
using System.Net.Http; using System.Threading; using System.Threading.Tasks; namespace Haos.Develop.HttpRequest.Samples { public class ColationDelegatingHandler:DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { //此處實現過濾邏輯 return base.SendAsync(request, cancellationToken); } } }
var Host = new HostBuilder() .ConfigureAppConfiguration(builder => { builder.AddCommandLine(args); }) .ConfigureServices((context, services) => { services.AddHttpClient<RequestClient>() //注冊過濾程序 .AddHttpMessageHandler<ColationDelegatingHandler>(); }) .UseConsoleLifetime() .Build();
四、基於Polly的處理程序
Polly 以表達策略,例如以流暢且線程安全的方式處理重試、斷路器、超時、Bulkhead 隔離和回退。Microsoft.Extensions.Http.Polly NuGet 包中提供 Polly 擴展實現將 Polly 策略用於配置的 HttpClient 實例。
Polly 添加策略分為三種
1. AddTransientHttpErrorPolicy:是處理Http請求的錯誤,如HTTP 5XX 的狀態碼,HTTP 408 的狀態碼 以及System.Net.Http.HttpRequestException異常
2. AddPolicyHandler:添加自定義策列
3. AddPolicyHandlerFromRegistry:從Policy注冊表集合里面選擇添加
a. AddTransientHttpErrorPolicy
.ConfigureServices((context, services) => { services.AddHttpClient<RequestClient>() .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(3, t => TimeSpan.FromMilliseconds(500))) //或。上下都是定義了,錯誤重試上面是間隔都是500毫秒,下面則定義了每次重試的時間間隔 .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10) })); })
b. AddPolicyHandler
先定義策略,在通過AddPolicyHandler方法添加,改方法接收一個泛型的IAsyncPolicy<HttpResponseMessage>。HttpResponseMessage我理解為出站請求上下文
.ConfigureServices((context, services) => { var retryPolicy = Policy.Handle<HttpRequestException>() .OrResult<HttpResponseMessage>(response => { //此處實現處理改異常的邏輯 return true; }).WaitAndRetryAsync(3,t => TimeSpan.FromMilliseconds(50)); services.AddHttpClient<RequestClient>() .AddPolicyHandler(retryPolicy); })
retryPolicy:發生HttpRequestException的異常,並且OrResult返回結果為true,采用這個策略
c. AddPolicyHandlerFromRegistry
先注冊策略表服務,為策略表添加策略,最后通過AddPolicyHandlerFromRegistry方法選用某個或幾個策略
.ConfigureServices((context, services) => { //注冊,策略表服務 var registry = services.AddPolicyRegistry(); //創建策略 var retryPolicy = Policy.Handle<HttpRequestException>() .OrResult<HttpResponseMessage>(response => { //此處實現處理改異常的邏輯 return true; }).WaitAndRetryAsync(3, t => TimeSpan.FromMilliseconds(50)); registry.Add("registry1", retryPolicy); services.AddHttpClient<RequestClient>() .AddPolicyHandlerFromRegistry("registry1"); })
添加多個 Polly 處理程序嵌套 Polly 策略以增強功
分別定義三種策略,timeoutPolicy,noOpPolicy,retryPolicy 通過策略表的方式和自定義。添加多個策略。
.ConfigureServices((context, services) => { //注冊,策略表服務 var registry = services.AddPolicyRegistry(); //創建策略 var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10);//10秒超時 var noOpPolicy = Policy.NoOpAsync().AsAsyncPolicy<HttpResponseMessage>();//有時我們也需要一個沒有任何行為的策略,Polly系統默認提供了一個. var retryPolicy = Policy.Handle<HttpRequestException>() .OrResult<HttpResponseMessage>(response => { //此處實現處理改異常的邏輯 return true; }).WaitAndRetryAsync(3, t => TimeSpan.FromMilliseconds(50)); registry.Add("registry1", retryPolicy); registry.Add("registry2", timeoutPolicy); services.AddHttpClient<RequestClient>() .AddPolicyHandlerFromRegistry("registry1") .AddPolicyHandler(retryPolicy) .AddPolicyHandler(timeoutPolicy); })