Mud.HttpUtils.Resilience 2.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Mud.HttpUtils.Resilience --version 2.0.0
                    
NuGet\Install-Package Mud.HttpUtils.Resilience -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Mud.HttpUtils.Resilience" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Mud.HttpUtils.Resilience" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Mud.HttpUtils.Resilience" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Mud.HttpUtils.Resilience --version 2.0.0
                    
#r "nuget: Mud.HttpUtils.Resilience, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Mud.HttpUtils.Resilience@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Mud.HttpUtils.Resilience&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Mud.HttpUtils.Resilience&version=2.0.0
                    
Install as a Cake Tool

Mud.HttpUtils.Resilience

概述

Mud.HttpUtils.Resilience 是 Mud.HttpUtils 的弹性策略层,基于 Polly 提供重试、超时、熔断策略,通过装饰器模式增强 IEnhancedHttpClient

目标框架

  • netstandard2.0
  • net6.0
  • net8.0
  • net10.0

包含内容

核心类

说明
ResilientHttpClient IEnhancedHttpClient 的弹性装饰器,组合重试/超时/熔断策略
PollyResiliencePolicyProvider 基于 Polly 的策略提供器,根据 ResilienceOptions 创建策略
ResiliencePolicyResolver IResiliencePolicyResolver 实现,解耦 IHttpRequestExecutor 与具体弹性策略,封装请求克隆逻辑
HttpRequestMessageCloner HTTP 请求消息克隆工具,确保重试安全
ResilienceOptions 弹性策略配置选项
ResilienceConstants 弹性策略常量定义
IResiliencePolicyProvider 弹性策略提供器接口,支持自定义策略实现

策略组合顺序

组合策略执行顺序:重试(外层) → 熔断 → 超时(内层)

  • 每次请求先经过超时策略限制
  • 超时的请求会被熔断器统计
  • 重试策略在所有内层策略之外

超时配置说明HttpClient.Timeout(通过 MudHttpClientOptions.TimeoutSeconds 配置)与 Polly 的 TimeoutOptions.TimeoutSeconds 是两个独立的超时机制。

  • HttpClient.Timeout 是 .NET HttpClient 内置的全局超时,作用于整个请求生命周期(包括重试)。
  • TimeoutOptions.TimeoutSeconds 是 Polly 的单次请求超时,仅作用于单次尝试(每次重试独立计时)。
  • 建议将 HttpClient.Timeout 设置为略大于 Retry.MaxRetryAttempts × TimeoutOptions.TimeoutSeconds + 总重试延迟,避免 HttpClient 超时打断正常的重试流程。
  • 启用弹性策略后,如果未显式设置 HttpClient.Timeout,Polly 超时策略将作为主要超时控制。

请求克隆与大小限制

HttpRequestMessageCloner 用于在重试时克隆请求消息(因为 HttpRequestMessage 不可重用)。新增内容大小限制功能:

// 默认最大克隆大小为 10MB
public const long DefaultMaxContentSize = 10 * 1024 * 1024;

// 克隆时检查大小
var cloned = await HttpRequestMessageCloner.CloneAsync(request, maxContentSize: 10 * 1024 * 1024);

当请求体大小超过 MaxCloneContentSize 时,ResilientHttpClient 会自动跳过重试策略,避免克隆大请求体的性能开销。适用于大文件上传等场景。

重试回调机制

RetryOptions 提供 OnRetry 属性,支持在每次重试前执行自定义逻辑:

services.AddMudHttpUtils("myApi", "https://api.example.com", options =>
{
    options.Retry.MaxRetryAttempts = 3;
    options.Retry.OnRetry = async (exception, retryCount, delay) =>
    {
        Console.WriteLine($"第 {retryCount} 次重试,延迟 {delay.TotalMilliseconds}ms,异常: {exception?.Message}");
    };
});

OnRetry 签名为 Func<Exception?, int, TimeSpan, Task>,参数分别为:触发的异常(可能为 null)、重试次数(从 1 开始)、下次重试前的延迟时间。可用于日志记录、指标收集、动态调整重试策略等。

配置选项

ResilienceOptions

属性 类型 默认值 说明
Retry RetryOptions 重试策略配置
Timeout TimeoutOptions 超时策略配置
CircuitBreaker CircuitBreakerOptions 熔断策略配置
MaxCloneContentSize long 10485760 (10MB) 请求克隆的最大内容大小(字节),-1 表示不限制

RetryOptions

属性 类型 默认值 说明
Enabled bool true 是否启用重试策略
MaxRetryAttempts int 3 最大重试次数
DelayMilliseconds int 1000 基础延迟时间(毫秒)
UseExponentialBackoff bool true 是否使用指数退避
RetryStatusCodes int[]? null(运行时回退到 [408, 429, 500, 502, 503, 504] 触发重试的 HTTP 状态码
OnRetry Func<Exception?, int, TimeSpan, Task>? null 重试回调函数

TimeoutOptions

属性 类型 默认值 说明
Enabled bool true 是否启用超时策略
TimeoutSeconds int 30 超时时间(秒)

CircuitBreakerOptions

属性 类型 默认值 说明
Enabled bool false 是否启用熔断策略
FailureThreshold int 5 触发熔断的阈值(含义取决于 SamplingDurationSeconds
BreakDurationSeconds int 30 熔断持续时间(秒)
SamplingDurationSeconds int 0 采样窗口时间(秒),大于 0 时启用高级熔断策略
MinimumThroughput int 10 采样窗口内最小请求数(仅高级熔断策略生效)

熔断模式说明

  • SamplingDurationSeconds = 0(默认)时,使用简单熔断策略FailureThreshold 表示连续失败次数
  • SamplingDurationSeconds > 0 时,使用高级熔断策略FailureThreshold 表示采样窗口内的失败率百分比(1-100)

安装

<PackageReference Include="Mud.HttpUtils.Resilience" Version="x.x.x" />

使用方式

代码配置

services.AddMudHttpResilienceDecorator(options =>
{
    // 重试策略
    options.Retry.Enabled = true;
    options.Retry.MaxRetryAttempts = 3;
    options.Retry.DelayMilliseconds = 1000;
    options.Retry.UseExponentialBackoff = true;
    options.Retry.RetryStatusCodes = [408, 429, 500, 502, 503, 504];
    options.Retry.OnRetry = async (ex, retryCount, delay) =>
    {
        logger.LogWarning("HTTP 请求重试 {RetryCount},延迟 {Delay}ms", retryCount, delay.TotalMilliseconds);
    };

    // 超时策略
    options.Timeout.Enabled = true;
    options.Timeout.TimeoutSeconds = 30;

    // 熔断策略
    options.CircuitBreaker.Enabled = true;
    options.CircuitBreaker.FailureThreshold = 5;
    options.CircuitBreaker.BreakDurationSeconds = 30;

    // 请求克隆大小限制
    options.MaxCloneContentSize = 10 * 1024 * 1024; // 10MB
});

配置文件绑定

services.AddMudHttpResilienceDecorator(configuration, "MudHttpResilience");

对应 appsettings.json

{
  "MudHttpResilience": {
    "MaxCloneContentSize": 10485760,
    "Retry": {
      "Enabled": true,
      "MaxRetryAttempts": 3,
      "DelayMilliseconds": 1000,
      "UseExponentialBackoff": true,
      "RetryStatusCodes": [408, 429, 500, 502, 503, 504]
    },
    "Timeout": {
      "Enabled": true,
      "TimeoutSeconds": 30
    },
    "CircuitBreaker": {
      "Enabled": true,
      "FailureThreshold": 5,
      "BreakDurationSeconds": 30,
      "SamplingDurationSeconds": 0,
      "MinimumThroughput": 10
    }
  }
}

高级熔断策略(基于采样窗口的失败率模式):

{
  "CircuitBreaker": {
    "Enabled": true,
    "FailureThreshold": 50,
    "BreakDurationSeconds": 30,
    "SamplingDurationSeconds": 60,
    "MinimumThroughput": 10
  }
}

高级模式下 FailureThreshold = 50 表示采样窗口内失败率达 50% 时触发熔断,至少需要 MinimumThroughput 次请求。

配置校验

ResilienceOptionsValidator 实现了 IValidateOptions<ResilienceOptions>,在选项绑定时自动执行跨选项校验:

  • Retry.EnabledTimeout.Enabled 同时为 true 时,校验重试总延迟(含指数退避)是否超过单次超时时间 Timeout.TimeoutSeconds。超出时 IOptions.Validate 返回失败,应用启动抛出异常。
  • Retry.EnabledTimeout.Enabledfalse 时,跳过此校验。

已知限制:此校验器无法检测 HttpClient.Timeout(通过 MudHttpClientOptions.TimeoutSeconds 配置)与 Polly 超时的跨选项冲突。建议用户手动确保 HttpClient.Timeout 略大于 Retry.MaxRetryAttempts × Timeout.TimeoutSeconds + 总重试延迟,避免 HttpClient 超时打断正常的重试流程。详见上方"超时配置说明"。

一站式注册

services.AddMudHttpUtils("myApi", "https://api.example.com", options =>
{
    options.Retry.MaxRetryAttempts = 3;
    options.Timeout.TimeoutSeconds = 30;
    options.MaxCloneContentSize = 5 * 1024 * 1024; // 5MB
});

大文件上传场景

对于大文件上传等场景,建议禁用重试或增大克隆限制:

// 方式一:增大克隆限制
options.MaxCloneContentSize = 100 * 1024 * 1024; // 100MB

// 方式二:禁用重试
options.Retry.Enabled = false;

// 方式三:不限制(不推荐)
options.MaxCloneContentSize = -1;

当请求体大小超过 MaxCloneContentSize 时,ResilientHttpClient 会记录警告日志并跳过重试,直接发送请求。

DI 服务注册方法

方法 说明
AddMudHttpResilience(configureOptions) 仅注册策略服务(不装饰客户端)
AddMudHttpResilience(configuration, sectionPath) 从配置绑定策略
AddMudHttpResilienceDecorator(configureOptions) 注册装饰器,为 IEnhancedHttpClient 添加弹性策略
AddMudHttpResilienceDecorator(configuration, sectionPath) 从配置绑定的装饰器注册
AddMudHttpUtils(clientName, configureHttpClient, configureResilienceOptions) 一站式注册 Client + Resilience
AddMudHttpUtils(clientName, configureHttpClient, enableResilience) 一站式注册,可选是否启用弹性策略
AddMudHttpUtils(clientName, baseAddress, configureResilienceOptions) 带基础地址的一站式注册
AddMudHttpUtils(clientName, baseAddress, enableResilience) 带基础地址的一站式注册,可选是否启用弹性策略
AddMudHttpUtils(clientName, configuration, configureHttpClient, sectionPath) 从配置绑定弹性策略的一站式注册
AddMudHttpUtils(clientName, configureEncryption, configureHttpClient, configureResilienceOptions) 带 AES 加密的一站式注册

注意AddMudHttpResilienceDecorator 必须在 AddMudHttpClient 之后调用。

依赖项

说明
Mud.HttpUtils.Abstractions 接口定义
Mud.HttpUtils.Client 客户端实现(装饰器目标)
Polly 弹性策略库
Microsoft.Extensions.Logging.Abstractions 日志抽象
Microsoft.Extensions.Options 选项模式

设计原则

  • 装饰器模式ResilientHttpClient 装饰 IEnhancedHttpClient,不修改原始实现
  • 策略组合:通过 Polly PolicyWrap 组合多种策略,执行顺序可控
  • 安全重试:通过 HttpRequestMessageCloner 克隆请求消息,确保重试安全
  • 性能保护:通过 MaxCloneContentSize 限制克隆大小,避免大请求体的克隆开销
  • 可观测性:通过 OnRetry 支持自定义重试回调,便于日志记录和指标收集;内置诊断事件负载(RetryDiagnosticPayloadTimeoutDiagnosticPayload)支持分布式追踪
  • 配置灵活:支持代码配置和配置文件绑定
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Mud.HttpUtils.Resilience:

Package Downloads
Mud.HttpUtils

Mud HttpUtils 元包,自动引用 Abstractions、Attributes、Client 和 Resilience 子模块。

GitHub repositories

This package is not used by any popular GitHub repositories.