Vin*_*mth 5 c# .net-core polly
在我的应用程序中,我使用Polly库来调用 API。
API 可以在响应中返回警告和错误。对于其中一些警告,我想重试 2 次,下次我想将响应返回给调用者。
这可以做到吗?
@StephenCleary 指出我应该只处理响应而不是抛出异常。
要检查响应,我需要等待内容。以下内容无法编译,有人能看到我该怎么做吗?
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(async msg =>
{
var content = await msg.Content.ReadAsStringAsync();
return content.Contains("errorcode123");
})
.WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
Run Code Online (Sandbox Code Playgroud)
这有几个部分。
首先,如果结果有警告,您不想抛出异常。那时您可能想重试,也可能不想;那里的代码还不能告诉。但是抛出异常意味着响应被丢弃,因此此时抛出异常是不正确的。
相反,该处理程序应该使用“有警告”标志来标记响应。这可以使用HttpRequestMessage.Properties(HttpRequestMessage.Options在 .NET 5 中)。像这样的东西:
private static readonly string IsInternalServerResponseKey = Guid.NewGuid().ToString("N");
...
var httpResponse = ...
var responseContent = ...
if (InternalServerResponse(responseContent))
{
httpResponse.RequestMessage.Properties[IsInternalServerResponseKey] = true;
}
Run Code Online (Sandbox Code Playgroud)
这样,请求/响应就会附加一个标志,代码的其他部分(特别是 Polly 重试处理程序)可以读取该标志。
解决方案的另一部分是重试计数。通常,Polly 具有确定是否应该重试的委托,并且这些委托是独立的 - 重试这种类型的异常,或者重试类似的响应。在这种情况下,您想要重试与特定形状匹配的响应,但前提是重试次数不多,并且如果重试次数太多并且响应与“重试”形状匹配,那么您不希望抛出异常但返回响应。
这是不寻常的,但是可行的。您需要捕获 Polly 上下文中的“外部考虑因素”(在本例中为重试计数)。然后,您的重试委托可以从上下文中提取重试计数,并据此做出决定。像这样的东西应该有效:
private static readonly string RetryCountKey = Guid.NewGuid().ToString("N");
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(response =>
{
return IsInternalServerResponse() && RetryCount() <= 2;
bool IsInternalServerResponse()
{
if (!response.RequestMessage.Properties.TryGetValue(IsInternalServerResponseKey, out var objValue) ||
objValue is not bool boolValue)
return false;
return boolValue;
}
int RetryCount()
{
if (!response.RequestMessage.GetPolicyExecutionContext().TryGetValue(RetryCountKey, out var objValue) ||
objValue is not int intValue)
return 0;
return intValue;
}
})
.WaitAndRetryAsync(2,
(retryAttempt, _) => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
(_, _, retryAttempt, context) => context[RetryCountKey] = retryAttempt);
}
Run Code Online (Sandbox Code Playgroud)
我还没有测试过这个;2传递到的WaitAndRetryAsync和2用于比较 的之间可能存在相差一的错误retryCount。
| 归档时间: |
|
| 查看次数: |
3089 次 |
| 最近记录: |