C#通过HttpClient+Polly实现自动重试与超时策略的操作指南

 更新时间:2025年11月10日 09:00:23   作者:拾荒的小海螺  
在微服务与API高度依赖的时代,网络请求的 可靠性 变得至关重要,网络波动、临时超时或第三方API不稳定,常常会导致应用抛出异常,为了解决这些问题,本文给大家介绍了在C#中如何通过HttpClient + Polly实现自动重试与超时策略,需要的朋友可以参考下

1、 简述

在微服务与 API 高度依赖的时代,网络请求的 可靠性 变得至关重要。网络波动、临时超时或第三方 API 不稳定,常常会导致应用抛出异常。为了解决这些问题,C# 中可以通过 HttpClient + Polly 实现:

  • ✅ 自动重试
  • ✅ 超时控制
  • ✅ 熔断保护
  • ✅ 弹性恢复

2、Polly 是什么?

Polly 是 .NET 中一个功能强大的弹性与瞬态故障处理库。
它允许开发者为代码执行定义策略,如:

  • Retry(重试)
  • Timeout(超时)
  • Circuit Breaker(熔断)
  • Fallback(降级)
  • Bulkhead Isolation(隔离舱)

在实际项目中,它与 HttpClientFactory 搭配使用,构成了强大的 网络容错体系

3、实践样例

3.1 环境准备

1️⃣ 创建一个项目

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 基础原理

使用 IHttpClientFactory 注册命名的 HttpClient,然后通过 AddPolicyHandler() 附加 Polly 策略,例如:

services.AddHttpClient("DemoClient")
    .AddPolicyHandler(GetRetryPolicy())
    .AddPolicyHandler(GetTimeoutPolicy());

这样创建的 HttpClient 会在每次请求时自动应用定义的重试与超时逻辑。

3.3 实现重试与超时策略

定义策略方法

using Polly;
using Polly.Extensions.Http;
using System;
using System.Net.Http;

public static class PolicyHandlers
{
    // 自动重试策略(最多重试 3 次)
    public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        return HttpPolicyExtensions
            .HandleTransientHttpError() // 处理 5xx、408、网络错误
            .WaitAndRetryAsync(
                retryCount: 3,
                sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // 2,4,8 秒退避
                onRetry: (outcome, timespan, retryAttempt, context) =>
                {
                    Console.WriteLine($"重试第 {retryAttempt} 次,等待 {timespan.TotalSeconds} 秒。");
                });
    }

    // 超时策略(每次请求最长 5 秒)
    public static IAsyncPolicy<HttpResponseMessage> GetTimeoutPolicy()
    {
        return Policy.TimeoutAsync<HttpResponseMessage>(5);
    }
}

上述策略实现了:

  • 自动 指数退避重试(2s → 4s → 8s)
  • 超时控制(单次请求超 5 秒自动中断)

注册 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");

        // 调用测试接口
        await TestHttpRequestAsync(client);
    }

    static async Task TestHttpRequestAsync(HttpClient client)
    {
        try
        {
            // 模拟 500 错误接口(会触发重试)
            var response = await client.GetAsync("500");
            Console.WriteLine($"最终状态码:{response.StatusCode}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"请求失败:{ex.Message}");
        }
    }
}

3.4 运行结果示例

运行后输出如下(每次重试等待更长时间):

重试第 1 次,等待 2 秒。
重试第 2 次,等待 4 秒。
重试第 3 次,等待 8 秒。
请求失败:响应状态码不成功,状态码: 500

说明:

  • 每次请求失败后 Polly 自动重试;
  • 达到最大次数后才抛出异常;
  • 如果请求超时,则会触发 TimeoutRejectedException

4、结合熔断(Circuit Breaker)

在部分 API 连续失败时,熔断 可以临时阻止新的请求,以保护系统资源。

public static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(
            handledEventsAllowedBeforeBreaking: 2, // 连续 2 次错误触发熔断
            durationOfBreak: TimeSpan.FromSeconds(10), // 熔断 10 秒
            onBreak: (outcome, timespan) => Console.WriteLine($"熔断开启 {timespan.TotalSeconds} 秒"),
            onReset: () => Console.WriteLine("熔断恢复"),
            onHalfOpen: () => Console.WriteLine("熔断半开,尝试恢复..."));
}

注册方式:

services.AddHttpClient("ResilientClient", client =>
{
    client.BaseAddress = new Uri("https://httpstat.us/");
})
.AddPolicyHandler(PolicyHandlers.GetRetryPolicy())
.AddPolicyHandler(PolicyHandlers.GetTimeoutPolicy())
.AddPolicyHandler(PolicyHandlers.GetCircuitBreakerPolicy());

5、结语

通过结合 HttpClient + Polly,我们可以让应用:

  • 在网络波动时自动重试;
  • 遇到卡顿时及时超时;
  • 遇到频繁失败时主动熔断;
  • 自动恢复服务健康状态。
功能说明
HttpClientFactory管理连接生命周期,防止 Socket 耗尽
Polly Retry自动重试机制,防止瞬态错误
Polly Timeout避免请求挂起太久
Polly Circuit Breaker熔断保护,防止雪崩故障
组合策略构建高可用、可恢复的 API 调用体系

这是一种现代 .NET 微服务中最常见、也是最推荐的 弹性策略组合

以上就是C#通过HttpClient+Polly实现自动重试与超时策略的操作指南的详细内容,更多关于C# HttpClient+Polly自动重试与超时策略的资料请关注脚本之家其它相关文章!

相关文章

  • C#数据结构之顺序表(SeqList)实例详解

    C#数据结构之顺序表(SeqList)实例详解

    这篇文章主要介绍了C#数据结构之顺序表(SeqList)实现方法,结合实例形式较为详细的分析了顺序表的定义、原理与具体实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11
  • Unity3D实现飞机大战游戏(2)

    Unity3D实现飞机大战游戏(2)

    这篇文章主要为大家详细介绍了Unity3D实现飞机大战游戏的第二部分,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • Parallel.For循环与普通for循环的性能比较

    Parallel.For循环与普通for循环的性能比较

    这篇文章介绍了Parallel.For循环与普通for循环的性能比较,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • 利用C#如何给PDF文档添加文本与图片页眉

    利用C#如何给PDF文档添加文本与图片页眉

    页眉常用于显示文档的附加信息,我们可以在页眉中插入文本或者图形,例如,页码、日期、公司徽标、文档标题、文件名或作者名等等。那么我们如何以编程的方式添加页眉呢?这篇文章主要介绍了利用C#如何给PDF文档添加文本与图片页眉的相关资料,需要的朋友可以参考下
    2017-01-01
  • C#利用正则表达式实现获取字符串中汉字的数量

    C#利用正则表达式实现获取字符串中汉字的数量

    这篇文章主要为大家详细介绍了C#如何利用正则表达式实现获取字符串中汉字的数量,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • c# 通过代码开启或关闭防火墙

    c# 通过代码开启或关闭防火墙

    这篇文章主要介绍了c# 通过代码开启或关闭防火墙的示例,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-10-10
  • C#通过rabbitmq实现定时任务(延时队列)

    C#通过rabbitmq实现定时任务(延时队列)

    工作中经常会有定时任务的需求,常见的做法可以使用Timer、Quartz、Hangfire等组件,本文使用C#通过rabbitmq实现定时任务(延时队列),感兴趣的可以了解一下
    2021-05-05
  • C#判断字符编码的方法总结(六种方法)

    C#判断字符编码的方法总结(六种方法)

    这篇文章主要介绍了C#判断字符编码的方法,结合实例形式总结分析了六种C#判断字符编码的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • C#封装将函数封装为接口dll的简单步骤指南

    C#封装将函数封装为接口dll的简单步骤指南

    在C#中,封装函数为接口并打包成DLL是实现代码重用和模块化的常见方法,此过程包括创建类库项目、定义接口、实现接口、编译项目生成DLL文件,这种方法适用于需要在多个项目间共享功能时使用,需要的朋友可以参考下
    2024-11-11
  • C#使用Socket实现本地多人聊天室

    C#使用Socket实现本地多人聊天室

    这篇文章主要为大家详细介绍了C#使用Socket实现本地多人聊天室,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02

最新评论