在构建分布式系统或微服务架构时,面对网络波动、超时或服务不可用等瞬态故障是常见的挑战。为提高系统的稳定性和可靠性,.NET 提供了 Polly 库,允许开发者定义重试、断路器、超时等容错策略。本文将通过具体示例,演示如何在 .NET 应用中使用 Polly 实现这些策略。

1. 安装 Polly 库
首先,使用 NuGet 包管理器安装 Polly 库:
dotnet add package Polly
2. Polly 重试策略示例
重试策略用于在请求失败时自动重试,适用于网络波动等瞬态故障场景。
using Polly;
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var httpClient = new HttpClient();
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));
await retryPolicy.ExecuteAsync(async () =>
{
var response = await httpClient.GetAsync("https://example.com");
response.EnsureSuccessStatusCode();
Console.WriteLine("Request succeeded.");
});
}
}
在上述示例中,WaitAndRetryAsync 方法定义了一个指数退避的重试策略,最多重试 3 次,每次重试的间隔时间呈指数增长。
3. Polly 断路器策略示例
断路器策略用于在连续失败达到一定阈值时,暂时中断请求,防止系统被故障请求淹没。
using Polly;
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var httpClient = new HttpClient();
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));
for (int i = 0; i < 5; i++)
{
try
{
await circuitBreakerPolicy.ExecuteAsync(async () =>
{
var response = await httpClient.GetAsync("https://example.com");
response.EnsureSuccessStatusCode();
Console.WriteLine("Request succeeded.");
});
}
catch (Exception ex)
{
Console.WriteLine($"Request failed: {ex.Message}");
}
}
}
}
在这个示例中,CircuitBreakerAsync 方法定义了一个断路器策略,当连续 2 次请求失败时,断路器会在 30 秒内打开,期间所有请求都会被拒绝。
4. Polly 超时策略示例
超时策略用于限制请求的最大执行时间,防止请求长时间挂起。
using Polly;
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var httpClient = new HttpClient();
var timeoutPolicy = Policy
.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(5));
try
{
var response = await timeoutPolicy.ExecuteAsync(() =>
httpClient.GetAsync("https://example.com"));
response.EnsureSuccessStatusCode();
Console.WriteLine("Request succeeded.");
}
catch (TimeoutRejectedException)
{
Console.WriteLine("Request timed out.");
}
}
}
在这个示例中,TimeoutAsync 方法定义了一个超时策略,限制请求的最大执行时间为 5 秒。
5. Polly 组合策略示例
Polly 允许将多个策略组合使用,以应对复杂的故障场景。
using Polly;
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var httpClient = new HttpClient();
var retryPolicy = Policy
.Handle<HttpRequestException>()
.WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));
var policyWrap = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);
try
{
await policyWrap.ExecuteAsync(async () =>
{
var response = await httpClient.GetAsync("https://example.com");
response.EnsureSuccessStatusCode();
Console.WriteLine("Request succeeded.");
});
}
catch (Exception ex)
{
Console.WriteLine($"Request failed: {ex.Message}");
}
}
}
在这个示例中,WrapAsync 方法将重试策略和断路器策略组合在一起,确保在请求失败时,先进行重试,再根据断路器策略判断是否继续请求。
6. 最佳实践建议
- 合理配置策略参数:根据实际业务需求,合理设置重试次数、超时时间等参数,避免过度重试或过短的超时时间。
- 日志记录:在策略中添加日志记录,便于故障排查和性能分析。
- 测试策略效果:在开发和测试环境中模拟故障,验证策略的有效性。
- 避免策略滥用:对于非瞬态故障(如 4xx 错误),应避免使用重试策略,以免加重系统负担。
通过上述示例和最佳实践,你可以在 .NET 应用中有效地使用 Polly 库,实现重试、断路器、超时等容错策略,提升系统的稳定性和可靠性。