Roy*_*mir 4 c# dotnet-httpclient .net-core polly retry-logic
我将 Polly ( Microsoft.Extensions.Http.Polly) 与 .net core 一起使用,并进行此配置(使用无效的 URL,用于测试):
private static void RegisterServices()
{
var collection = new ServiceCollection();
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(2); // Timeout for an individual try
collection.AddHttpClient<INetworkService, NetworkService>(url=>
{
url.BaseAddress = new Uri("http://www.google.com:81"); //test bad url
})
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(timeoutPolicy); ;
_serviceProvider = collection.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
哪里GetRetryPolicy:
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode != HttpStatusCode.OK)
.Or<TimeoutRejectedException>()
.Or<TaskCanceledException>()
.Or<OperationCanceledException>()
.WaitAndRetryAsync(3, retryAttempt =>
{
return TimeSpan.FromSeconds(2);
},
onRetry: (response, delay, retryCount, context) =>
{
Console.WriteLine($"______PollyAttempt_____ retryCount:{retryCount} ");
});
}
Run Code Online (Sandbox Code Playgroud)
输出是:
_ PollyAttempt retryCount:1
_ PollyAttempt retryCount:2
_ PollyAttempt retryCount:3
异常 : (TimeoutException) 通过 TimeoutPolicy 异步执行的委托未在超时内完成。
我想在上次尝试失败后发送一封电子邮件。
问题:
我怎样才能捕获最后的异常?是否有任何内置机制可以让我知道 Polly 失败了?
(我当前工作的代码:https ://pastebin.pl/view/a2566d51 )
让我们从一个根本不使用 Polly 的简单设置开始:
private static void RegisterServices()
{
var collection = new ServiceCollection();
collection.AddHttpClient<INetworkService, NetworkService>(sonol =>
{
sonol.BaseAddress = new Uri("http://www.google.com:81");
});
_serviceProvider = collection.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
TaskCanceledException. 换句话说,HttpClient 取消请求,因为它没有收到任何响应。现在让我们稍微调整一下 HttpClient 设置:
private static void RegisterServices()
{
var collection = new ServiceCollection();
collection.AddHttpClient<INetworkService, NetworkService>(sonol =>
{
sonol.Timeout = TimeSpan.FromSeconds(3); // << NEW CODE
sonol.BaseAddress = new Uri("http://www.google.com:81");
});
_serviceProvider = collection.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
TaskCanceledException现在,注释掉这个超时设置,让我们连接超时策略:
private static void RegisterServices()
{
var collection = new ServiceCollection();
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(2);
collection.AddHttpClient<INetworkService, NetworkService>(sonol =>
{
//sonol.Timeout = TimeSpan.FromSeconds(3);
sonol.BaseAddress = new Uri("http://www.google.com:81");
})
.AddPolicyHandler(timeoutPolicy); // << NEW CODE
_serviceProvider = collection.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
TimeoutRejectedException.
InnerException是原来的TaskCanceledException。最后让我们添加重试策略:
private static void RegisterServices()
{
var collection = new ServiceCollection();
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(2);
collection.AddHttpClient<INetworkService, NetworkService>(sonol =>
{
//sonol.Timeout = TimeSpan.FromSeconds(3);
sonol.BaseAddress = new Uri("http://www.google.com:81");
})
.AddPolicyHandler(Policy.WrapAsync(GetRetryPolicy(), timeoutPolicy)); // << NEW CODE
//.AddPolicyHandler(timeoutPolicy);
_serviceProvider = collection.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
TimeoutRejectedException.
TaskCanceledException.更新:抓住评论的本质
我知道所有尝试都失败的点在哪里?
当你的 Polly 装饰HttpClient抛出 时TimeoutRejectedException,你可以确定所有尝试都失败了。因此,您应该将GetAsynctry-catch 包装在类型化客户端内。
我应该检查异常以查看它是 timeoutException 吗?
如果 url 格式错误,它将抛出不同的异常。因此,如果您发现TimeoutRejectedException这将意味着下游不可用或过载。
我是否需要捕获第一个 TimeoutRejectedException 异常才能识别退休失败?
从消费者的角度来看,会有一个例外。重试策略将抛出它
Handle<>或 Or<>调用显式列出的异常都被视为未处理。这意味着无需重试,策略就会抛出该错误。换句话说,TimeoutRejectedException如果客户端在给定时间段内没有收到下游系统的答复,则会抛出该异常。HttpRequestException但如果存在一些网络问题,它也可能会抛出。
HttpRequestException.| 归档时间: |
|
| 查看次数: |
2139 次 |
| 最近记录: |