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自动重试与超时策略的资料请关注脚本之家其它相关文章!

相关文章

  • 使用checked语句防止数据溢出的解决方法

    使用checked语句防止数据溢出的解决方法

    本篇文章是对用checked语句防止数据溢出的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • Python结合wxPython构建安全高速的文件移动工具

    Python结合wxPython构建安全高速的文件移动工具

    这篇文章主要介绍了一款基于Python和wxPython开发的桌面文件移动工具FolderMoverPro,旨在解决Windows系统文件复制中的常见痛点,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2026-03-03
  • C#中如何生成安装包

    C#中如何生成安装包

    这篇文章主要介绍了C#中如何生成安装包问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • 利用Distinct()内置方法对List集合的去重问题详解

    利用Distinct()内置方法对List集合的去重问题详解

    这篇文章主要给大家介绍了关于利用Distinct()内置方法对List集合的去重问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 逐步讲解快速排序算法及C#版的实现示例

    逐步讲解快速排序算法及C#版的实现示例

    快速排序在时间复杂度同为O(N*logN)的几种排序方法中效率较高,因而比较常用,接下来这里就来逐步讲解快速排序算法及C#版的实现示例
    2016-06-06
  • C#读写文件的方法汇总

    C#读写文件的方法汇总

    C#读写文件的方法汇总,需要的朋友可以参考一下
    2013-03-03
  • Unity实现模型点击事件的方法

    Unity实现模型点击事件的方法

    这篇文章主要介绍了Unity实现模型点击事件的方法,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-05-05
  • C# 可空值类型的具体使用

    C# 可空值类型的具体使用

    在C#编程中,可空值类型是一个非常有用的特性,它允许我们将值类型表示为可空,这在处理一些可能没有值的情况时非常方便,具有一定的参考价值,感兴趣的可以了解一下
    2025-07-07
  • C# Socket数据接收的三种实现方式

    C# Socket数据接收的三种实现方式

    本文主要介绍了C# Socket数据接收的三种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • C#中将字符串转换为整型的三种解决方法总结

    C#中将字符串转换为整型的三种解决方法总结

    本篇文章是对C#中将字符串转换为整型的三种解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06

最新评论