C#通過HttpClient+Polly實(shí)現(xiàn)自動(dòng)重試與超時(shí)策略的操作指南
1、 簡述
在微服務(wù)與 API 高度依賴的時(shí)代,網(wǎng)絡(luò)請求的 可靠性 變得至關(guān)重要。網(wǎng)絡(luò)波動(dòng)、臨時(shí)超時(shí)或第三方 API 不穩(wěn)定,常常會(huì)導(dǎo)致應(yīng)用拋出異常。為了解決這些問題,C# 中可以通過 HttpClient + Polly 實(shí)現(xiàn):
- ? 自動(dòng)重試
- ? 超時(shí)控制
- ? 熔斷保護(hù)
- ? 彈性恢復(fù)
2、Polly 是什么?
Polly 是 .NET 中一個(gè)功能強(qiáng)大的彈性與瞬態(tài)故障處理庫。
它允許開發(fā)者為代碼執(zhí)行定義策略,如:
- Retry(重試)
- Timeout(超時(shí))
- Circuit Breaker(熔斷)
- Fallback(降級)
- Bulkhead Isolation(隔離艙)
在實(shí)際項(xiàng)目中,它與 HttpClientFactory 搭配使用,構(gòu)成了強(qiáng)大的 網(wǎng)絡(luò)容錯(cuò)體系。
3、實(shí)踐樣例
3.1 環(huán)境準(zhǔn)備
1?? 創(chuàng)建一個(gè)項(xiàng)目
dotnet new console -n HttpClientPollyDemo cd HttpClientPollyDemo
2?? 安裝 NuGet 包
dotnet add package Microsoft.Extensions.Http dotnet add package Polly dotnet add package Polly.Extensions.Http
3.2 基礎(chǔ)原理
使用 IHttpClientFactory 注冊命名的 HttpClient,然后通過 AddPolicyHandler() 附加 Polly 策略,例如:
services.AddHttpClient("DemoClient")
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetTimeoutPolicy());
這樣創(chuàng)建的 HttpClient 會(huì)在每次請求時(shí)自動(dòng)應(yīng)用定義的重試與超時(shí)邏輯。
3.3 實(shí)現(xiàn)重試與超時(shí)策略
定義策略方法
using Polly;
using Polly.Extensions.Http;
using System;
using System.Net.Http;
public static class PolicyHandlers
{
// 自動(dòng)重試策略(最多重試 3 次)
public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError() // 處理 5xx、408、網(wǎng)絡(luò)錯(cuò)誤
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // 2,4,8 秒退避
onRetry: (outcome, timespan, retryAttempt, context) =>
{
Console.WriteLine($"重試第 {retryAttempt} 次,等待 {timespan.TotalSeconds} 秒。");
});
}
// 超時(shí)策略(每次請求最長 5 秒)
public static IAsyncPolicy<HttpResponseMessage> GetTimeoutPolicy()
{
return Policy.TimeoutAsync<HttpResponseMessage>(5);
}
}
上述策略實(shí)現(xiàn)了:
- 自動(dòng) 指數(shù)退避重試(2s → 4s → 8s)
- 超時(shí)控制(單次請求超 5 秒自動(dòng)中斷)
注冊 HttpClient 與策略
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var services = new ServiceCollection();
// 注冊 HttpClient + Polly 策略
services.AddHttpClient("ResilientClient", client =>
{
client.BaseAddress = new Uri("https://httpstat.us/");
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientPollyDemo");
})
.AddPolicyHandler(PolicyHandlers.GetRetryPolicy())
.AddPolicyHandler(PolicyHandlers.GetTimeoutPolicy());
var provider = services.BuildServiceProvider();
var factory = provider.GetRequiredService<IHttpClientFactory>();
var client = factory.CreateClient("ResilientClient");
// 調(diào)用測試接口
await TestHttpRequestAsync(client);
}
static async Task TestHttpRequestAsync(HttpClient client)
{
try
{
// 模擬 500 錯(cuò)誤接口(會(huì)觸發(fā)重試)
var response = await client.GetAsync("500");
Console.WriteLine($"最終狀態(tài)碼:{response.StatusCode}");
}
catch (Exception ex)
{
Console.WriteLine($"請求失?。簕ex.Message}");
}
}
}
3.4 運(yùn)行結(jié)果示例
運(yùn)行后輸出如下(每次重試等待更長時(shí)間):
重試第 1 次,等待 2 秒。 重試第 2 次,等待 4 秒。 重試第 3 次,等待 8 秒。 請求失敗:響應(yīng)狀態(tài)碼不成功,狀態(tài)碼: 500
說明:
- 每次請求失敗后 Polly 自動(dòng)重試;
- 達(dá)到最大次數(shù)后才拋出異常;
- 如果請求超時(shí),則會(huì)觸發(fā)
TimeoutRejectedException。
4、結(jié)合熔斷(Circuit Breaker)
在部分 API 連續(xù)失敗時(shí),熔斷 可以臨時(shí)阻止新的請求,以保護(hù)系統(tǒng)資源。
public static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(
handledEventsAllowedBeforeBreaking: 2, // 連續(xù) 2 次錯(cuò)誤觸發(fā)熔斷
durationOfBreak: TimeSpan.FromSeconds(10), // 熔斷 10 秒
onBreak: (outcome, timespan) => Console.WriteLine($"熔斷開啟 {timespan.TotalSeconds} 秒"),
onReset: () => Console.WriteLine("熔斷恢復(fù)"),
onHalfOpen: () => Console.WriteLine("熔斷半開,嘗試恢復(fù)..."));
}
注冊方式:
services.AddHttpClient("ResilientClient", client =>
{
client.BaseAddress = new Uri("https://httpstat.us/");
})
.AddPolicyHandler(PolicyHandlers.GetRetryPolicy())
.AddPolicyHandler(PolicyHandlers.GetTimeoutPolicy())
.AddPolicyHandler(PolicyHandlers.GetCircuitBreakerPolicy());
5、結(jié)語
通過結(jié)合 HttpClient + Polly,我們可以讓應(yīng)用:
- 在網(wǎng)絡(luò)波動(dòng)時(shí)自動(dòng)重試;
- 遇到卡頓時(shí)及時(shí)超時(shí);
- 遇到頻繁失敗時(shí)主動(dòng)熔斷;
- 自動(dòng)恢復(fù)服務(wù)健康狀態(tài)。
| 功能 | 說明 |
|---|---|
| HttpClientFactory | 管理連接生命周期,防止 Socket 耗盡 |
| Polly Retry | 自動(dòng)重試機(jī)制,防止瞬態(tài)錯(cuò)誤 |
| Polly Timeout | 避免請求掛起太久 |
| Polly Circuit Breaker | 熔斷保護(hù),防止雪崩故障 |
| 組合策略 | 構(gòu)建高可用、可恢復(fù)的 API 調(diào)用體系 |
這是一種現(xiàn)代 .NET 微服務(wù)中最常見、也是最推薦的 彈性策略組合。
以上就是C#通過HttpClient+Polly實(shí)現(xiàn)自動(dòng)重試與超時(shí)策略的操作指南的詳細(xì)內(nèi)容,更多關(guān)于C# HttpClient+Polly自動(dòng)重試與超時(shí)策略的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#數(shù)據(jù)結(jié)構(gòu)之順序表(SeqList)實(shí)例詳解
這篇文章主要介紹了C#數(shù)據(jù)結(jié)構(gòu)之順序表(SeqList)實(shí)現(xiàn)方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了順序表的定義、原理與具體實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Unity3D實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲(2)
這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲的第二部分,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
Parallel.For循環(huán)與普通for循環(huán)的性能比較
這篇文章介紹了Parallel.For循環(huán)與普通for循環(huán)的性能比較,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
C#利用正則表達(dá)式實(shí)現(xiàn)獲取字符串中漢字的數(shù)量
這篇文章主要為大家詳細(xì)介紹了C#如何利用正則表達(dá)式實(shí)現(xiàn)獲取字符串中漢字的數(shù)量,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
C#通過rabbitmq實(shí)現(xiàn)定時(shí)任務(wù)(延時(shí)隊(duì)列)
工作中經(jīng)常會(huì)有定時(shí)任務(wù)的需求,常見的做法可以使用Timer、Quartz、Hangfire等組件,本文使用C#通過rabbitmq實(shí)現(xiàn)定時(shí)任務(wù)(延時(shí)隊(duì)列),感興趣的可以了解一下2021-05-05
C#使用Socket實(shí)現(xiàn)本地多人聊天室
這篇文章主要為大家詳細(xì)介紹了C#使用Socket實(shí)現(xiàn)本地多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

