C# 如何使用 Polly 实现弹性策略 断路器与重试机制

来源:AI编程作者:美园和花头衔:网络博主
导读:本期聚焦于小伙伴创作的《C# 如何使用 Polly 实现弹性策略 断路器与重试机制》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C# 如何使用 Polly 实现弹性策略 断路器与重试机制》有用,将其分享出去将是对创作者最好的鼓励。

在 C# 开发中,调用外部服务或数据库时经常会遇到临时故障,比如网络闪断、服务过载等,这类故障通常不需要立即报错,通过重试或者暂时切断调用链路就能恢复。Polly 是一个轻量级的 .NET 弹性瞬态故障处理库,提供了丰富的策略来应对这类问题,其中重试和断路器是最常用的两种策略。

C# 如何使用 Polly 实现弹性策略 断路器与重试机制

Polly 基础准备

首先需要在项目中引入 Polly 包,如果是 .NET Core 或 .NET 5+ 项目,可以通过 NuGet 安装 Polly 最新稳定版,安装完成后即可在代码中引用相关命名空间。

// 安装命令:Install-Package Polly 或 dotnet add package Polly
using Polly;
using Polly.CircuitBreaker;

实现重试机制

重试机制适用于 transient 故障,也就是临时出现的、大概率会自动恢复的错误,比如网络偶发超时。Polly 提供了多种重试策略,包括固定间隔重试、指数退避重试等。

简单重试策略

下面的示例实现了最多重试 3 次,每次重试间隔 1 秒的策略,当调用外部接口抛出 HttpRequestException 时触发重试。

// 定义重试策略,最多重试3次,每次间隔1秒,仅在抛出HttpRequestException时重试
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(1));

// 使用策略执行接口调用逻辑
var result = retryPolicy.Execute(() =>
{
    // 模拟调用外部HTTP接口
    var client = new HttpClient();
    return client.GetAsync("http://ipipp.com/api/test").Result;
});

指数退避重试

如果服务故障是短暂的,指数退避重试可以避免短时间内大量重试加重服务负担,每次重试间隔按指数增长。

// 指数退避重试,最多重试5次,首次间隔1秒,之后每次间隔翻倍
var exponentialRetryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1)));

// 执行调用
exponentialRetryPolicy.Execute(() =>
{
    var client = new HttpClient();
    return client.GetAsync("http://ipipp.com/api/test").Result;
});

实现断路器策略

断路器的作用是当服务出现连续故障时,暂时切断调用链路,避免无意义的重试浪费资源,同时给故障服务恢复的时间。断路器有三个状态:关闭、打开、半打开。

  • 关闭状态:正常执行调用,当连续失败次数达到阈值时切换到打开状态
  • 打开状态:直接拒绝调用,经过设定的熔断时间后切换到半打开状态
  • 半打开状态:允许少量调用尝试,如果成功则切换到关闭状态,失败则回到打开状态

基础断路器实现

下面的示例定义了连续失败 5 次后熔断,熔断时间为 30 秒的断路器策略。

// 定义断路器策略:连续5次失败后熔断,熔断时长30秒
var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(5, TimeSpan.FromSeconds(30));

// 执行调用
try
{
    circuitBreakerPolicy.Execute(() =>
    {
        var client = new HttpClient();
        return client.GetAsync("http://ipipp.com/api/test").Result;
    });
}
catch (BrokenCircuitException)
{
    // 捕获断路器打开时的异常,执行降级逻辑
    Console.WriteLine("服务当前不可用,已触发熔断,请稍后再试");
}

组合重试与断路器策略

实际业务中通常会将重试和断路器组合使用,先执行重试策略,重试多次失败后触发断路器,避免对故障服务持续发起请求。

// 先定义重试策略
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(1));

// 再定义断路器策略
var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(5, TimeSpan.FromSeconds(30));

// 组合策略:先执行重试,重试失败后触发断路器
var combinedPolicy = Policy.Wrap(retryPolicy, circuitBreakerPolicy);

// 使用组合策略执行调用
try
{
    combinedPolicy.Execute(() =>
    {
        var client = new HttpClient();
        return client.GetAsync("http://ipipp.com/api/test").Result;
    });
}
catch (BrokenCircuitException)
{
    Console.WriteLine("服务不可用,已熔断");
}
catch (HttpRequestException)
{
    Console.WriteLine("调用失败,重试后仍未成功");
}

策略的复用与依赖注入

在实际项目中,策略通常定义为单例,通过依赖注入的方式提供给各个业务模块使用,避免重复创建策略实例。

// 在Startup或Program中注册策略
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(1));

var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreaker(5, TimeSpan.FromSeconds(30));

var combinedPolicy = Policy.Wrap(retryPolicy, circuitBreakerPolicy);

// 注册为单例
builder.Services.AddSingleton(combinedPolicy);

// 在业务类中注入使用
public class TestService
{
    private readonly IAsyncPolicy _policy;

    public TestService(IAsyncPolicy policy)
    {
        _policy = policy;
    }

    public async Task CallApi()
    {
        await _policy.ExecuteAsync(async () =>
        {
            var client = new HttpClient();
            return await client.GetAsync("http://ipipp.com/api/test");
        });
    }
}

注意事项

  • 重试策略不要用于非 transient 故障,比如参数错误、权限不足等,这类错误重试没有意义
  • 断路器的阈值和熔断时间需要根据实际业务场景调整,避免阈值过低频繁熔断,或者阈值过高起不到保护作用
  • 组合策略时,顺序很重要,通常是重试在前,断路器在后,避免重试触发断路器
  • 如果调用的是同步方法,使用 Execute 方法,异步方法使用 ExecuteAsync 方法,不要混用

PollyC#断路器重试机制弹性策略修改时间:2026-06-28 19:09:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。