如何利用HttpClientFactory實(shí)現(xiàn)簡(jiǎn)單的熔斷降級(jí)
前言
在2.1之后,有不少新東西,其中HttpClientFactory算是一個(gè)。HttpClientFactory涉及的東西也不算少,三四種clients , 請(qǐng)求中間件,與Polly的結(jié)合,生命周期等。
Steeltoe的組件升級(jí)到2.1后,不少示例代碼已經(jīng)使用HttpClientFactory了。當(dāng)然這是個(gè)題外話。
這里主要講的是與Polly的結(jié)合,來(lái)完成簡(jiǎn)單的熔斷降級(jí)。在這之前,還是先看看關(guān)于HttpClientFactory最簡(jiǎn)單的用法。
HttpClientFactory的簡(jiǎn)單使用
用個(gè)簡(jiǎn)單的控制臺(tái)程序來(lái)演示
這里就只是獲取一下?tīng)顟B(tài)碼,沒(méi)有獲取實(shí)際的內(nèi)容。
static async Task<string> BasicUsage() { var serviceCollection = new ServiceCollection(); serviceCollection.AddHttpClient(); var services = serviceCollection.BuildServiceProvider(); var clientFactory = services.GetService<IHttpClientFactory>(); var client = clientFactory.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Get, "https://www.github.com"); var response = await client.SendAsync(request).ConfigureAwait(false); return response.StatusCode.ToString(); }
其實(shí)主要的操作就是AddHttpClient,然后通過(guò)HttpClientFactory創(chuàng)建一個(gè)HttpClient對(duì)象,有了HttpClient對(duì)象,下面的操作應(yīng)該就不用多說(shuō)了。
然后在Main方法調(diào)用
Console.WriteLine($"BasicUsage, StatusCode = {BasicUsage().GetAwaiter().GetResult()}");
用法感覺(jué)并沒(méi)有太多的差別。下面來(lái)看看與Polly的結(jié)合。
HttpClientFactory和Polly的結(jié)合
Polly的wiki頁(yè)面已經(jīng)有了這兩者結(jié)合使用的文檔了。
https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory
其實(shí)現(xiàn)在對(duì)于我們來(lái)說(shuō),要想對(duì)http請(qǐng)求使用Polly的一些特性已經(jīng)非常的簡(jiǎn)單了。
我們?cè)谑褂玫臅r(shí)候要添加Microsoft.Extensions.Http.Polly的Nuget包。
先來(lái)看看使用Polly的三種擴(kuò)展方法
擴(kuò)展方法 | 說(shuō)明 |
---|---|
AddTransientHttpErrorPolicy | 主要是處理Http請(qǐng)求的錯(cuò)誤,如HTTP 5XX 的狀態(tài)碼,HTTP 408 的狀態(tài)碼 以及System.Net.Http.HttpRequestException異常。 |
AddPolicyHandler | 自定義,和傳統(tǒng)定義Polly的方式保持一致 |
AddPolicyHandlerFromRegistry | 從Policy集合(也是自定義的)里面選擇自己想要的。 |
后面的操作,是用的AddPolicyHandler。
由于我們要實(shí)現(xiàn)熔斷降級(jí),所以,我們必不可少的要用到CircuitBreakerPolicy和FallbackPolicy,同時(shí)為了方便演示,再加個(gè)TimeoutPolicy。
由于涉及到多個(gè)Policy,所以我們必須要確定他們的執(zhí)行順序!
Polly的wiki頁(yè)面有個(gè)示例,還配了一幅很詳細(xì)的時(shí)序圖。
一句話來(lái)說(shuō)就是最先起作用的,還是最后添加的那個(gè)。
下面就新建一個(gè)API項(xiàng)目,用來(lái)演示一下。
修改ConfigureServices方法,具體如下
public void ConfigureServices(IServiceCollection services) { var fallbackResponse = new HttpResponseMessage(); fallbackResponse.Content = new StringContent("fallback"); fallbackResponse.StatusCode = System.Net.HttpStatusCode.TooManyRequests; services.AddHttpClient("cb", x => { x.BaseAddress = new Uri("http://localhost:8000"); x.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Test"); }) //fallback .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().FallbackAsync(fallbackResponse, async b => { Logger.LogWarning($"fallback here {b.Exception.Message}"); })) //circuit breaker .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().CircuitBreakerAsync(2, TimeSpan.FromSeconds(4), (ex, ts) => { Logger.LogWarning($"break here {ts.TotalMilliseconds}"); }, () => { Logger.LogWarning($"reset here "); })) //timeout .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(1)); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
然后是在控制器去使用。
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private static int myCount = 0; private readonly IHttpClientFactory _clientFactory; public ValuesController(IHttpClientFactory clientFactory) { this._clientFactory = clientFactory; } // GET api/values/timeout [HttpGet("timeout")] public ActionResult<IEnumerable<string>> Timeout() { if (myCount < 3)//模擬超時(shí) { System.Threading.Thread.Sleep(3000); } myCount++; return new string[] { "value1", "value2" }; } // GET api/values [HttpGet("")] public async Task<string> GetAsync() { var client = _clientFactory.CreateClient("cb"); var request = new HttpRequestMessage(HttpMethod.Get, "/api/values/timeout"); var response = await client.SendAsync(request); var content = await response.Content.ReadAsStringAsync(); return content; } }
效果如下
前面幾次請(qǐng)求,會(huì)因?yàn)槌瑫r(shí)或熔斷,從而我們得到的結(jié)果是fallback。
過(guò)了4秒鐘后再請(qǐng)求,由于沒(méi)有超時(shí),正常拿到了結(jié)果,所以熔斷器會(huì)被reset。
來(lái)看看日志
比較清晰的看到了所有的操作。
總結(jié)
總體來(lái)說(shuō),HttpClientFactory還是很不錯(cuò)的。尤其是它可以直接使用Polly相關(guān)的特性。
部分示例代碼: HttpClientFactoryDemo
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- asp.net core為IHttpClientFactory添加動(dòng)態(tài)命名配置
- 如何在ASP.NET Core中使用HttpClientFactory
- 詳解如何在ASP.NET Core中使用IHttpClientFactory
- .net Core 使用IHttpClientFactory請(qǐng)求實(shí)現(xiàn)
- .Net Core下HTTP請(qǐng)求IHttpClientFactory示例詳解
- DotNetCore深入了解之HttpClientFactory類詳解
- .NET Core 2.1中HttpClientFactory的最佳實(shí)踐記錄
- .NET Core中的HttpClientFactory類用法詳解
相關(guān)文章
.Net筆記:System.IO之windows文件操作的深入分析
本篇文章是對(duì).Net中windows文件操作的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Asp.net MVC SignalR來(lái)做實(shí)時(shí)Web聊天實(shí)例代碼
本篇文章主要介紹了Asp.net SignalR來(lái)做實(shí)時(shí)Web聊天實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06ASP.NET設(shè)計(jì)網(wǎng)絡(luò)硬盤之刪除文件夾實(shí)現(xiàn)代碼
對(duì)于不再需要的文件/文件夾用戶有權(quán)限做刪除處理。這一節(jié)就介紹如何實(shí)現(xiàn)這一功能2012-10-10asp.net 按指定模板導(dǎo)出word,pdf實(shí)例代碼
這篇文章介紹了asp.net 按指定模板導(dǎo)出word,pdf實(shí)例代碼,有需要的朋友可以參考一下2013-09-09asp.net(C#)生成Code39條形碼實(shí)例 條碼槍可以掃描出
這篇文章主要介紹了asp.net(C#)生成Code39條形碼實(shí)例 條碼槍可以掃描出。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-02-02ASP.NET 5中使用AzureAD實(shí)現(xiàn)單點(diǎn)登錄
本文給大家介紹的是在ASP.NET 5中使用AzureAD實(shí)現(xiàn)單點(diǎn)登錄的方法和示例,有需要的小伙伴可以參考下。2015-07-07asp.net GridView的刪除對(duì)話框的兩種方法
本來(lái)這兩種方法,我已經(jīng)掌握。但是沒(méi)有總結(jié),今天朋友突然問(wèn)題,我竟然想不起來(lái),找了半天,現(xiàn)在亡羊補(bǔ)牢,趕快寫(xiě)在博客里。2009-04-04ASP.NET?Core使用EF創(chuàng)建模型(包含屬性、排除屬性、主鍵和生成值)
這篇文章介紹了ASP.NET?Core使用EF創(chuàng)建模型的的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04