.NET 8 中的Microsoft.Extensions.Http.Resilience库

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

5be3891b50ef6aeb4f852ba5656d2d23.png

这里就不得不提到 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库作为替代方案.

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

MethodMeanErrorStdDevRatioGen0AllocatedAlloc Ratio
StandardPipeline_Polly_V73.236 us0.0130 us0.0187 us1.000.14883816 B1.00
StandardPipeline_Polly_V83.104 us0.0237 us0.0317 us0.960.03811008 B0.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/ 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值