当前位置:

首页 > 编程开发 > C#怎么使用Refit和Polly组合_C#弹性HTTP客户端教程【推荐】

C#怎么使用Refit和Polly组合_C#弹性HTTP客户端教程【推荐】

Refit与Polly整合需通过IHttpClientFactory挂载策略,AddPolicyHandler不能直接用于Refit接口。指数退避必须添加随机抖动防重试风暴。通过onRetryAsync捕获重试原因并判空。超时策略需禁用HttpClient.Timeout,否则劫持Polly超时。

在实际项目里,把 Refit 和 Polly 整合起来做弹性 HTTP 客户端,看着简单,但真落地时有好几个容易踩的坑。下面就把几个最关键的环节拆开说清楚,从注册策略、指数退避抖动,到重试原因捕捉、超时冲突,每个点都直接对应线上常见的“炸裂”场景。

Refit注册时需通过IHttpClientFactory挂Polly策略:先AddRefitClient,再ConfigureHttpClient,最后AddPolicyHandler;不可直接对Refit接口调用AddPolicyHandler,否则编译错误。

C#怎么使用Refit和Polly组合_C#弹性HTTP客户端教程【推荐】

Refit注册时怎么挂Polly策略

Refit 本身不直接支持策略注入,必须通过 IHttpClientFactory 中间层来实现。核心路径很简单:先用 AddRefitClient 注册 Refit 接口,接着用 AddPolicyHandler 挂上 Polly 策略,最后交给 DI 容器解析出带弹性的客户端。

常见错误是直接对 Refit 接口调用 AddPolicyHandler,这百分百编译报错——因为 Refit 的扩展方法返回的是 IServiceCollection,不是 IHttpClientBuilder,链式根本接不上。

  • 正确写法(.NET 6+ Program.cs):
    builder.Services    .AddRefitClient()    .ConfigureHttpClient(client => client.BaseAddress = new Uri("https://api.github.com/"))    .AddPolicyHandler(GetRetryPolicy())    .AddPolicyHandler(GetTimeoutPolicy());
  • GetRetryPolicy() 必须返回 IAsyncPolicy 类型,不能是泛型 Policy,否则编译就过不去。
  • 如果同时需要熔断 + 重试,要用 PolicyWrap 组合,千万不能链式调用两次 AddPolicyHandler(后者会直接覆盖前者,逻辑全白写)。

为什么指数退避要加抖动(jitter)

纯指数退避(比如 1s → 2s → 4s)看着挺合理,但在高并发场景下很容易引发“重试风暴”——大量请求在同一个毫秒级时间点集体重试,下游服务瞬间被压垮。所以加随机抖动不是优化项,是生产环境的硬性要求。

举个例子,不加抖动的策略:TimeSpan.FromSeconds(Math.Pow(2, retryAttempt));加抖动后应该改成:TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) + TimeSpan.FromMilliseconds(new Random().Next(100, 300))。

  • 抖动值建议控制在 100–500ms 区间,太大把退避效果削弱了,太小又起不到错峰作用。
  • new Random() 在高并发下容易产生重复种子,推荐用 Random.Shared(.NET 6+)或者注入线程安全的 IRandom。
  • Polly.Extensions.Http 提供了 WaitAndRetryAsync 的抖动重载,但需要手动传入 sleepDurationProvider,没有一键开关。

Refit + Polly 下如何捕获具体重试原因

默认情况下,Refit 抛出的异常(比如 ApiException)只是最终失败结果,中间哪次重试失败、为什么失败,完全看不到。因此必须通过 onRetryAsync 回调来记录细节。

关键点在于:回调里的 outcome.Exception 是原始异常,outcome.Result 是 HttpResponseMessage,两者都可能为 null,一定要做判空处理。

  • 示例回调写法:
    onRetryAsync: (outcome, span, attempt, context) =>{    var ex = outcome.Exception?.InnerException ?? outcome.Exception;    var statusCode = outcome.Result?.StatusCode ?? default;    Console.WriteLine($"第{attempt}次重试,等待{span.TotalSeconds:F1}s,状态码:{statusCode},异常:{ex?.GetType().Name}");}
  • 不要在回调里 throw 新异常,否则会中断重试流程,直接变成失败。
  • 如果用了 PolicyWrap(比如重试+熔断),onRetryAsync 只对重试策略生效,熔断触发时走的是 onBreak 回调。

超时策略和 HttpClient.Timeout 冲突吗

会冲突,而且 HttpClient.Timeout 优先级更高——它会在 Polly 的 TimeoutPolicy 触发前就抛出 TaskCanceledException,导致 Polly 超时策略压根不执行。

解决办法也很直接:必须禁用 HttpClient.Timeout,在 ConfigureHttpClient 中设为 TimeSpan.Zero 或者干脆不设置;所有超时逻辑全部交给 Polly 去控制。

  • 错误写法:
    .ConfigureHttpClient(c => {    c.BaseAddress = ...;    c.Timeout = TimeSpan.FromSeconds(10); // ❌ 这会劫持 Polly 超时
  • 正确写法:
    .ConfigureHttpClient(c => c.BaseAddress = ...); // 不设 Timeout
    ,再用 AddPolicyHandler(Policy.TimeoutAsync(10))。
  • Policy.TimeoutAsync 对 HttpResponseMessage 生效,而 HttpClient.Timeout 对整个 SendAsync 生命周期生效,语义完全不一样。

Refit 和 Polly 的组合看着简单,实际落地时最常卡在策略类型匹配、回调空引用、以及 HttpClient 原生超时的隐式干扰上——这些地方不报编译错、也没日志,但运行时行为完全不符合预期。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发 C#
相关文章 更多
winforms教程自学入门与基础开发步骤详解
winforms教程自学入门与基础开发步骤详解

本教程详细讲解如何使用Visual Studio创建WinForms项目,通过添加按钮和标签控件并编写点击事件代码,实现一个基础的计数器功能,适合C#初学者快速上手Windows窗体应用开发。

谈编程与编程语言
谈编程与编程语言

编程的本质是创造性的严谨翻译,通过for、if和函数调用实现重复计算任务。语言发展让集成度提高,门槛降低但竞争加剧。程序员需培养整体架构能力,抓住思想精髓而非追逐新技术,方能长远发展。

什么是面向接口编程、面向过程编程、面向对象编程?
什么是面向接口编程、面向过程编程、面向对象编程?

面向接口编程通过接口解耦,降低耦合度并提升可扩展性和维护性,是面向对象思想的精髓。面向过程编程将问题拆解为步骤,用函数依次执行。面向对象编程将事物抽象为对象,封装属性和方法,通过对象协作解决问题。

我对编程的一些感悟
我对编程的一些感悟

编程这件事,说到底是门手艺活,但又不全是手艺。把代码写出来容易,把代码写好、写出境界,那就得看功夫了。今天聊几个核心判断,算是多年敲键盘的一点沉淀。 一、语言是功夫,思路是内功 编程语言五花八门,就像武林高手会的功夫一样,但想成为顶尖高手,内功必须深厚。内功到了,学新功夫就是分分钟的事。看过《倚天屠

c#如何使用abstract类_c#abstract类看这一篇就够了_保姆级教程
c#如何使用abstract类_c#abstract类看这一篇就够了_保姆级教程

abstract类不能被直接实例化,子类必须用override实现其所有抽象方法。抽象类可实现接口,并以抽象方法转发接口成员。抽象类不能与sealed共用,其抽象方法默认隐式virtual且无方法体。可包含字段、属性等非抽象成员。

c#如何删除文件_c#删除文件的正确用法与注意事项
c#如何删除文件_c#删除文件的正确用法与注意事项

C#删除文件前应先判断存在性以防异常,注意权限不足和文件被占用。File.Delete与FileInfo.Delete功能相同,后者适合多次操作。无异步删除方法,推荐后台执行或限流以避免阻塞。

c#如何使用EmguCV_c#EmguCV的最佳实践与常见坑点
c#如何使用EmguCV_c#EmguCV的最佳实践与常见坑点

在EmguCV中,进行Bitmap转Image时,需先转为24位无Alpha格式,以避免颜色错乱问题;Image转Bitmap时,建议使用Mat或ImageBox控件,以有效减少内存拷贝;跨线程处理时,应使用Mat.Clone()进行深拷贝,以确保数据安全;DLL加载失败时,需设置x64平台目标,并确保native库在输出目录中。

C#怎么实现图表生成 C#如何用LiveCharts和OxyPlot绘制柱状图折线图饼图【图表】
C#怎么实现图表生成 C#如何用LiveCharts和OxyPlot绘制柱状图折线图饼图【图表】

C#图表生成中,LiveCharts需用ChartValues数据集合,并在更新后触发重绘;OxyPlot饼图需启用交互与标签;包引用务必注意版本适配;导出图片需在布局完成后操作,并校正DPI缩放以确保清晰度。

C#怎么实现过滤器Filter_C# ASP.NET Core过滤器详解教程【进阶】
C#怎么实现过滤器Filter_C# ASP.NET Core过滤器详解教程【进阶】

ASP.NETCore过滤器需关注执行顺序、作用域与DI生命周期。接口实现需手动注册,特性继承更常用但需满足构造函数要求。全局注册时注意scoped服务注入问题,Order值须显式设置以控制同类型过滤器执行顺序。异常过滤器仅捕获操作方法内异常,模型绑定与授权失败须分别处理。

c#如何实现鼠标钩子_c#鼠标钩子完整教程与实战案例
c#如何实现鼠标钩子_c#鼠标钩子完整教程与实战案例

实现全局鼠标钩子需使用SetWindowsHookEx配合WH_MOUSE_LL,窗体级事件仅捕获本进程消息。回调函数必须为静态且标记特定签名,禁止阻塞操作。通过Marshal.PtrToStructure解析lParam获取坐标与按键状态。钩子生命周期绑定线程,需注意注册线程持续运行并双重卸载,避免句柄泄漏。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Postman macOS版
Postman macOS版
Mac

Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。

Docker Desktop macOS版
Docker Desktop macOS版
Mac

Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。

Android Studio macOS版
Android Studio macOS版
Mac

Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。

WINDOWS 更多
Postman Windows版
Postman Windows版
Windows

Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等

Docker Desktop Windows版
Docker Desktop Windows版
Windows

Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。

Android Studio Windows版
Android Studio Windows版
Windows

Android Studio 是 Google 面向 Android 应用开发提供的官方集成开发环境,以 IntelliJ IDEA 为基础,集成智能代码编辑、Gradle 构建、设备模拟、界面预览、调试测试及性能分析工具,