c# - 当http请求超时时重试多次使用polly c#
问题描述
我的初衷是在请求本身超时时重试多次,例如尝试与另一个已关闭几秒钟的微服务通信时,希望它是暂时的失败。如果有一个更简单的解决方案来做到这一点就足够了。我决定使用包装策略手动设置每次重试超时,希望达到相同的结果。
我在这里看到了不使用 httpclientfactory 的类似解决方案Use a specific timeout connected to a retrypolicy,但它对我不起作用。
我的代码如下所示:
services.AddHttpClient("retryclient", client =>
{
client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
Policy.HandleResult<HttpResponseMessage>(r =>
{
return r.StatusCode == HttpStatusCode.NotFound; //(1)
}).
.OrTransiesntHttpError().
WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
onRetry: (exception, timespan, retryAttempt, context) =>
{ // using servs to log // });
}).WrapAsync(Policy.TimeoutAsync(1)));
当我尝试访问“未找到”地址而不包装超时策略时,我检查了重试策略是否有效,并且它工作正常。我也尝试将第 (1) 行与状态代码一起使用,HttpStatusCode.RequestTimeout
而不是在我的情况下找不到,但它不起作用。
当我使用包装并尝试访问已关闭的服务时,它会Polly.Timeout.TimeoutRejectedException
按照我的预期在第一次尝试时抛出 a ,但不会再次重试。我想不出一种方法来重试多次,或者为每次重试设置超时,或者只是在请求本身超时而不使用超时策略时。
编辑:在进一步阅读 https://cm.engineering/transient-timeouts-and-the-retry-rabbit-hole-net-4-5-f406cebbf194之后,我的问题似乎出在我无法访问的策略处理中HttpClient 的取消令牌。我假设我可以通过覆盖链接中所示的 sendAsync 方法来修复它。在创建工厂时是否有一种优雅的方式来做同样的事情?
解决方案
HttpClientFactory 上的Polly 文档在标记为应用超时的部分中对此进行了介绍:
如果任何个人尝试超时,您可能希望重试策略重试。为此,请让重试策略处理
TimeoutRejectedException
Polly 的超时策略引发的问题。
所以:
services.AddHttpClient("retryclient", client =>
{
client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
Policy.HandleResult<HttpResponseMessage>(r =>
{
return r.StatusCode == HttpStatusCode.NotFound; //(1)
}).
.OrTransientHttpError()
.Or<TimeoutRejectedException>() // ** ADDED **
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
onRetry: (exception, timespan, retryAttempt, context) =>
{ // using servs to log // });
})
.WrapAsync(Policy.TimeoutAsync(1)));
Polly 正确地将 传递CancellationToken
给内部.SendAsync()
调用;对此不需要任何改变。
推荐阅读
- google-cloud-data-fusion - 运行简单数据融合管道以从 Bigquery 导出数据并写入 GCS 时出现连接超时错误
- php - 如何在php中显示成功从mysql中删除记录的消息
- validation - 一个人可以有空名字吗?
- javascript - PIE 切片的颜色不是唯一的
- python - 如何创建 Azure DevOps 管道以部署到 SharePoint?
- node.js - Electron 不尊重 `webPreferences.defaultFontFamily`?
- android - 有没有办法让我在 React Native 中创建一个文件夹并将 JSON 文件放置在 Android 和 iOS 的移动本地存储中?
- datetime - 如何以特定格式获取昨天的日期?
- asp.net-mvc - 将对象列表绑定到控制器 MVC 模型时获取 Null
- mysql - 如何在同一张桌子上加入两次?