.NET8中的Microsoft.Extensions.Http.Resilience库

net8,microsoft,extensions,http,resilience · 浏览次数 : 219

小编点评

## .NET 如何处理服务发现和熔断限流? .NET 使用以下库来处理服务发现和熔断限流: * **Microsoft.Extensions.ServiceDiscovery**:用于注册和发现服务。 * **Microsoft.Extensions.Resilience**:用于实现熔断限流。 **服务发现** 1. 使用 `AddHttpClient` 注册服务。 2. 创建 `IHttpClientBuilder` 实例。 3. 使用 `AddTransientHttpErrorPolicy` 配置熔断限流。 4. 使用 `AddStandardResilienceHandler` 配置其他弹性配置。 **熔断限流** 1. 创建 `IHttpClientBuilder` 实例。 2. 使用 `AddTransientHttpErrorPolicy` 配置熔断限流。 3. 使用 `AddCircuitBreaker` 配置熔断器。 4. 使用 `AddStandardResilienceHandler` 配置其他弹性配置。 **示例代码** ```csharp // 使用 Microsoft.Extensions.Http.Resilience builder.Services.AddHttpClient("qrcode", client => { client.BaseAddress = "http://qrcode"; }); builder.Services.AddStandardResilienceHandler(options => { options.Retry.MaxRetryAttempts = 3; options.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(30); options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(5); }); // 使用 Microsoft.Extensions.ServiceDiscovery builder.Services.AddHttpClient("qrcode", client => { client.BaseAddress = "http://qrcode"; }); builder.Services.AddTransientHttpErrorPolicy((builder) => { var retryPolicy = builder.WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(5d)); return retryPolicy.WrapAsync(circuitBreakerPolicy); }); ``` **注意** * 这些库都支持多种弹性策略,例如熔断、重试和超时。 * 可根据实际需求选择不同的策略。 * 可以使用 `Configure` 方法在配置文件中配置弹性设置。

正文

接上一篇,https://www.cnblogs.com/vipwan/p/18129361 借助Aspire中新增的Microsoft.Extensions.ServiceDiscovery库,我们可以很容易的做到服务发现,那么服务节点的熔断限流以及重试等弹性机制.NET是怎么处理的呢?
比如下图的微服务场景:

image

这里就不得不提到 Microsoft.Extensions.Http.Polly这个Polly的封装库了,这个库是从NETCore2.1增加的,我们可以很容易的对IHttpClientBuilder扩展弹性机制,比如下面的代码:

builder.Services.AddHttpClient("qrcode", client =>
{
    client.BaseAddress = new("http://qrcode");
})
.AddTransientHttpErrorPolicy((builder) =>
{
    // 重试3次,每次间隔5秒
    var retryPolicy = builder.WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(5d));
    // 熔断器,失败3次后,30秒内不再请求
    var circuitBreakerPolicy = builder.CircuitBreakerAsync(3, TimeSpan.FromSeconds(30));
    // 重试策略包装熔断器
    return retryPolicy.WrapAsync(circuitBreakerPolicy);
});

然鹅Microsoft.Extensions.Http.Polly库是早些年就存在的产物了,针对Polly V8及后续的版本巨硬在 NET8后增加了 Microsoft.Extensions.Http.Resilience库作为替代方案.

下面是巨硬给出的两个版本的性能差异:

Method Mean Error StdDev Ratio Gen0 Allocated Alloc Ratio
StandardPipeline_Polly_V7 3.236 us 0.0130 us 0.0187 us 1.00 0.1488 3816 B 1.00
StandardPipeline_Polly_V8 3.104 us 0.0237 us 0.0317 us 0.96 0.0381 1008 B 0.26

速度较快的同时,基于 Polly v8 构建的Microsoft.Extensions.Http.Resilience使用的内存减少了4倍之多。
所以至NET8+以后我推荐使用Microsoft.Extensions.Http.Resilience替代Microsoft.Extensions.Http.Polly

下面我们使用新库实现模拟的策略:


builder.Services.AddHttpClient("qrcode", client =>
{
    client.BaseAddress = new("http://qrcode");
})

// Microsoft.Extensions.Http.Polly实现的代码:
.AddTransientHttpErrorPolicy((builder) =>
{
    // 重试3次,每次间隔5秒
    var retryPolicy = builder.WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(5d));
    // 熔断器,失败3次后,30秒内不再请求
    var circuitBreakerPolicy = builder.CircuitBreakerAsync(3, TimeSpan.FromSeconds(30));

    // 重试策略包装熔断器
    return retryPolicy.WrapAsync(circuitBreakerPolicy);
})
// Microsoft.Extensions.Http.Resilience实现代码:
.AddStandardResilienceHandler(options =>
{
    options.Retry.MaxRetryAttempts = 3;
    options.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(30);// 总的超时时间
    options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(5);//每次重试的超时时间
    options.CircuitBreaker.BreakDuration = TimeSpan.FromSeconds(30);//熔断时间
})
;

当然大多数情况弹性机制是放到配置文件或者其他持久层的这个时候我们可以使用Configure(IConfigurationSection) 或者 Configure(Action<HttpStandardResilienceOptions, IServiceProvider>)


.AddStandardResilienceHandler(options =>
{
    options.Retry.MaxRetryAttempts = 3;
    options.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(5);// 超时时间
    options.AttemptTimeout.Timeout = TimeSpan.FromSeconds(5);//每次重试的超时时间
    options.CircuitBreaker.BreakDuration = TimeSpan.FromSeconds(30);//熔断时间
})
.Configure((options, sp) =>
{
    // 配置来自自定义的Provider
    var myResiliencePolicy = sp.GetRequiredService<IResiliencePolicyProvider>().GetResiliencePolicy("MyPolicy");
    options.Retry.MaxRetryAttempts = myResiliencePolicy.Retry.MaxRetryAttempts;
});

从代码上来说也优雅了一些

当然也可以使用AddResilienceHandler扩展方法实现一些比较个性化的配置需求,这个就比较类似于Microsoft.Extensions.Http.Polly:

builder.Services.AddHttpClient("qrcode", client =>
{
    client.BaseAddress = new("http://qrcode");
})
.AddResilienceHandler("MyPolicy", builder =>
{
    builder.AddTimeout(TimeSpan.FromSeconds(5));
    builder.AddRetry(new HttpRetryStrategyOptions
    {
        MaxRetryAttempts = 3,
        Delay = TimeSpan.FromSeconds(2),
        MaxDelay = TimeSpan.FromSeconds(10),
    });
    //其他的机制....
});

参考文档 https://github.com/dotnet/docs/blob/main/docs/core/resilience/http-resilience.md

https://devblogs.microsoft.com/dotnet/building-resilient-cloud-services-with-dotnet-8/

与.NET8中的Microsoft.Extensions.Http.Resilience库相似的内容:

.NET8中的Microsoft.Extensions.Http.Resilience库

接上一篇,https://www.cnblogs.com/vipwan/p/18129361 借助Aspire中新增的Microsoft.Extensions.ServiceDiscovery库,我们可以很容易的做到服务发现,那么服务节点的熔断限流以及重试等弹性机制.NET是怎么处理的呢? 比如下图

NET8中增加的简单适用的DI扩展库Microsoft.Extensions.DependencyInjection.AutoActivation

这个库提供了在启动期间实例化已注册的单例,而不是在首次使用它时实例化。 单例通常在首次使用时创建,这可能会导致响应传入请求的延迟高于平时。在注册时创建实例有助于防止第一次Request请求的SLA 以往我们要在注册的时候启动单例可能会这样写: //注册: services.AddSingleton<

在.NET 8 RC1 版本中 MAUI、ASP.NET Core 和 EF8 的新特性

从年初2 月份发布第一个预览版,经历7个预览版后,Microsoft 西雅图时间9月13日发布了 .NET 8 RC 1: https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-rc1/[1], 这是该框架在 11 月初正式发布之前的两个

.NET周刊【9月第3期 2023-09-17】

国内文章 在.NET 8 RC1 版本中 MAUI、ASP.NET Core 和 EF8 的新特性 https://www.cnblogs.com/shanyou/p/17698428.html 从年初2 月份发布第一个预览版,经历7个预览版后,Microsoft 西雅图时间9月13日发布了 .NE

【.NET8】访问私有成员新姿势UnsafeAccessor(下)

前言 书接上回,我们讨论了在.NET8中新增的UnsafeAccessor,并且通过UnsafeAccessor访问了私有成员,这极大的方便了我们代码的编写,当然也聊到了它当前存在的一些局限性,那么它的性能到底如何?我们今天就来实际测试一下。 测试代码 话不多说,直接上代码,本次测试代码如下: us

造轮子之asp.net core identity

在前面我们完成了应用最基础的功能支持以及数据库配置,接下来就是我们的用户角色登录等功能了,在asp.net core中原生Identity可以让我们快速完成这个功能的开发,在.NET8中,asp.net core identity支持了WebApi的注册登录。这让我们在WebApi中可以更爽快的使用

.NET8 Identity Register

分享给需要帮助的人:记一次 IdentityAPI 中注册的源码解读:设置用户账户为未验证状态,以及除此之外更安全的做法: 延迟用户创建。包含了对优缺点的说明,以及适用场景。 在ASP.NET 8 Identity 中注册API的源码如下: routeGroup.MapPost("/register

.Net8 AddKeyedScoped键值key注册服务异常

异常描述:This service descriptor is keyed. Your service provider may not support keyed services. 场景:.Net8 WebAPI应用程序中使用AutoFac替代了默认的DI容器 当使用键值注册服务后: build

【.NET 8】ASP.NET Core计划 - 支持更完善的AOT发布

.NET7.0刚发布不久,.NET社区开始了.NET8.0的开发,重心重新回到了新功能的迭代。 我们知道在.NET7.0中一个令人激动的特新就是支持了NativeAOT,我们可以通过NativeAOT生成本机程序,由于无需JIT编译,所以无需安装.NET Runtime,也进一步的提升了.程序的启动

Asp-Net-Core开发笔记:给SwaggerUI加上登录保护功能

前言 在 SwaggerUI 中加入登录验证,是我很早前就做过的,不过之前的做法总感觉有点硬编码,最近 .Net8 增加了一个新特性:调用 MapSwagger().RequireAuthorization 来保护 Swagger UI ,但官方的这个功能又像半成品一样,只能使用 postman c