首页 > 其他分享 >.NET6之MiniAPI(二十四):用Polly重试

.NET6之MiniAPI(二十四):用Polly重试

时间:2022-11-29 21:34:39浏览次数:37  
标签:MiniAPI AddTransientHttpErrorPolicy FromMilliseconds return TimeSpan 重试 NET6 pol

  为了保障系统的稳定和安全,在调用三方服务时,可以增加重试和熔断。重试是调用一次失败后再试几试,避免下游服务一次闪断,就把整个链路终止;熔断是为了防止太多的次数的无效访问,导致系统不可知异常。

  Polly是独立的重试机制的三方库,这里只说明在使用httpclient时,请求下游api时的重试和熔断。需要引入NuGet包Microsoft.Extensions.Http.Polly。

  先看一个简单的重试

using Polly;

var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddHttpClient("RetryClient", httpclient =>
{
httpclient.BaseAddress = new Uri("http://localhost:5258");
})
.AddTransientHttpErrorPolicy(policyBuilder => policyBuilder.RetryAsync(3));

var app = builder.Build();
//调用httpclient
app.MapGet("/test", async (IHttpClientFactory httpClientFactory) =>
{
try
{
var httpClient = httpClientFactory.CreateClient("RetryClient");
var content = await httpClient.GetStringAsync("other-api");
Console.WriteLine(content);
return "ok";
}
catch (Exception exc)
{
if (!Count.Time.HasValue)
{
Count.Time = DateTime.Now;
}
return $"{exc.Message} 【次数:{Count.I++}】 【{Count.Time.Value.ToString("yyyy-MM-dd HH:mm:ss.fffffff")}】";
}
});

//被调用的接口,返回状态码500
app.MapGet("/other-api", (ILogger<Program> logger) =>
{
logger.LogInformation($"失败:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff")}");
return Results.StatusCode(500);
});
app.Run();

static class Count
{
public static int I = 1;

public static DateTime? Time;
}

  返回的结果:

.NET6之MiniAPI(二十四):用Polly重试_Polly

   通过AddTransientHttpErrorPolicy(policyBuilder => policyBuilder.RetryAsync(3));我们让请求进行了3次重试,加上原本的一次,就是4次请求。在红色框时,会发现请求集中在极短的时间内,如果下游服务有故障,可能不会在这么短的时间内自动恢复,更好的做法是:根据重试的次数,来延长(或随机,或自建延时算法)请求的时间,比如:

.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.WaitAndRetryAsync(3, retryNumber =>
{
switch (retryNumber)
{
case 1:
return TimeSpan.FromMilliseconds(500);
case 2:
return TimeSpan.FromMilliseconds(1000);
case 3:
return TimeSpan.FromMilliseconds(1500);
default:
return TimeSpan.FromMilliseconds(100);
}
}));

  这时的结果如下,基本按照我们设置的时间来重试的:

.NET6之MiniAPI(二十四):用Polly重试_Polly_02

   还有几种重试策略,如下:

//一直重试
.AddTransientHttpErrorPolicy(policyBuilder => policyBuilder.RetryForeverAsync());
//每2秒重试一次
.AddTransientHttpErrorPolicy(policyBuilder => policyBuilder.WaitAndRetryForeverAsync(retryNumber =>
{
Console.WriteLine(retryNumber);
return TimeSpan.FromSeconds(2);
}));
//在5秒内4次请求,如果50%失败,就熔断10秒
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.AdvancedCircuitBreakerAsync(0.5d, TimeSpan.FromSeconds(5), 4, TimeSpan.FromSeconds(10)));

  熔断是保护服务的手段,在本例中具体用法如下:

builder.Services
.AddHttpClient("RetryClient", httpclient =>
{
httpclient.BaseAddress = new Uri("http://localhost:5258");
})
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.WaitAndRetryAsync(3, retryNumber =>
{
switch (retryNumber)
{
case 1:
return TimeSpan.FromMilliseconds(500);
case 2:
return TimeSpan.FromMilliseconds(1000);
case 3:
return TimeSpan.FromMilliseconds(1500);
default:
return TimeSpan.FromMilliseconds(100);
}
}))
//熔断
.AddTransientHttpErrorPolicy(policyBuilder =>
policyBuilder.CircuitBreakerAsync(6, TimeSpan.FromSeconds(30)));

  CircuitBreaker控制如果有6次失败的请求,就暂停30秒,具体提示如下:

.NET6之MiniAPI(二十四):用Polly重试_Polly_03

 

  想要更快更方便的了解相关知识,可以关注微信公众号 


.NET6之MiniAPI(二十四):用Polly重试_Polly_04

 

标签:MiniAPI,AddTransientHttpErrorPolicy,FromMilliseconds,return,TimeSpan,重试,NET6,pol
From: https://blog.51cto.com/axzxs/5897094

相关文章

  • .NET6之MiniAPI(二十五):Dapper
    注:如果你使用Dapper一段时间了,这篇你可以跳过去了。在第十二篇中,我们聊过官方的ORM——EntityFramework,它可以把SQL细节都隐藏,这对于一些标准化的关系数据库项目非......
  • .NET6之MiniAPI(二十四):用Polly重试
    为了保障系统的稳定和安全,在调用三方服务时,可以增加重试和熔断。重试是调用一次失败后再试几试,避免下游服务一次闪断,就把整个链路终止;熔断是为了防止太多的次数的无效......
  • .NET6之MiniAPI(二十四):用Polly重试
    为了保障系统的稳定和安全,在调用三方服务时,可以增加重试和熔断。重试是调用一次失败后再试几试,避免下游服务一次闪断,就把整个链路终止;熔断是为了防止太多的次数的无效......
  • .NET6之MiniAPI(二十五):Dapper
    注:如果你使用Dapper一段时间了,这篇你可以跳过去了。在第十二篇中,我们聊过官方的ORM——EntityFramework,它可以把SQL细节都隐藏,这对于一些标准化的关系数据库项目......
  • .NET6之MiniAPI(二十三):Refit
    本篇是与上篇HttpClient有关联的,有前篇中,我们是直接使用HttpClient来发出请求的,所有的请求信息都是我们根据需要自己来填充的。那Refit是什么呢?它是一个让我们调用API......
  • .NET6之MiniAPI(二十三):Refit
    本篇是与上篇HttpClient有关联的,有前篇中,我们是直接使用HttpClient来发出请求的,所有的请求信息都是我们根据需要自己来填充的。那Refit是什么呢?它是一个让我们调用API就......
  • .NET6之MiniAPI(二十二):HttpClient
    说明:本篇不是说明HttpClient怎么使用,而以分享在asp.netcoreminiapi框架下,HttpClient的引入和使用方式。我们在业务开发中,免不了调用三方的服务,这时就会用到Htt......
  • .NET6之MiniAPI(二十二):HttpClient
    说明:本篇不是说明HttpClient怎么使用,而以分享在asp.netcoreminiapi框架下,HttpClient的引入和使用方式。我们在业务开发中,免不了调用三方的服务,这时就会用到Htt......
  • .NET6之MiniAPI(二十一):限流
    限流,可以网络的基础设施进行配置实现,也可以在网关的地方进行限流,但服务本身的限流也不可或缺,因为当多副本时,一个副本故障,流量对于其他副本来说会提高,如果超过其承受请求量......
  • .NET6之MiniAPI(二十一):限流
    限流,可以网络的基础设施进行配置实现,也可以在网关的地方进行限流,但服务本身的限流也不可或缺,因为当多副本时,一个副本故障,流量对于其他副本来说会提高,如果超过其承受请求量......