调整代码以使用内置比率策略
我想实现与下面的策略相同的行为,并以内置的比塔级策略,即记录器消息并读取重试标头并等待需要等待但使用内置比率策略的确切秒数。
尝试
// TODO: No logger message and not sure if it waits the time taken from the Retry-After header.
public static AsyncRateLimitPolicy Limit<T>(ILogger<T> logger)
{
return Policy.RateLimitAsync(RateLimitRetryCount, TimeSpan.FromSeconds(5));
}
工作
public static AsyncRetryPolicy<RestResponse> AsyncRateLimit<T>(ILogger<T> logger)
{
return Policy.HandleResult<RestResponse>(response => response.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(RateLimitRetryCount,
(attemptCount, restResponse, _) =>
{
var retryAfterHeader = restResponse?.Result?.Headers?.SingleOrDefault(h => h.Name == "Retry-After");
double secondsInterval = 0;
if (retryAfterHeader != null)
{
var value = retryAfterHeader.Value?.ToString();
if (!double.TryParse(value, out secondsInterval))
{
secondsInterval = Math.Pow(2, attemptCount);
}
}
return TimeSpan.FromSeconds(secondsInterval);
},
(response, timeSpan, retryCount, _) =>
{
logger.LogTrace(
"The API request has been rate limited. HttpStatusCode={StatusCode}. Waiting {Seconds} seconds before retry. Number attempt {RetryCount}. Uri={Url}; RequestResponse={Content}",
response.Result.StatusCode, timeSpan.TotalSeconds, retryCount, response.Result.ResponseUri, response.Result.Content);
return Task.CompletedTask;
});
}
I want to achieve the same behavior as the policy below with the built-in RateLimit policy, i.e. the logger message and to read the Retry-After header and wait the exact seconds that were needed to wait for but using the built-in RateLimit policy.
Attempt
// TODO: No logger message and not sure if it waits the time taken from the Retry-After header.
public static AsyncRateLimitPolicy Limit<T>(ILogger<T> logger)
{
return Policy.RateLimitAsync(RateLimitRetryCount, TimeSpan.FromSeconds(5));
}
Works
public static AsyncRetryPolicy<RestResponse> AsyncRateLimit<T>(ILogger<T> logger)
{
return Policy.HandleResult<RestResponse>(response => response.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(RateLimitRetryCount,
(attemptCount, restResponse, _) =>
{
var retryAfterHeader = restResponse?.Result?.Headers?.SingleOrDefault(h => h.Name == "Retry-After");
double secondsInterval = 0;
if (retryAfterHeader != null)
{
var value = retryAfterHeader.Value?.ToString();
if (!double.TryParse(value, out secondsInterval))
{
secondsInterval = Math.Pow(2, attemptCount);
}
}
return TimeSpan.FromSeconds(secondsInterval);
},
(response, timeSpan, retryCount, _) =>
{
logger.LogTrace(
"The API request has been rate limited. HttpStatusCode={StatusCode}. Waiting {Seconds} seconds before retry. Number attempt {RetryCount}. Uri={Url}; RequestResponse={Content}",
response.Result.StatusCode, timeSpan.TotalSeconds, retryCount, response.Result.ResponseUri, response.Result.Content);
return Task.CompletedTask;
});
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有多个问题,所以让我回答所有问题。
1)如何将记录仪注入策略?
您需要使用 polly的上下文。
上下文是在策略之外创建的。它被用作存储任何任意信息的容器
,然后通过
execute
/executeasync
调用最终您可以在任何用户委托中使用上下文(例如
>
>) onretry
/onretryAsync
)要检索传递的对象withlogger
andgetlogger
扩展方法2)在上述费率限制器工作中与重试的方式相同吗?
否。费率限制器是A 主动策略,可用于防止资源滥用。这意味着如果超过预定义的限制,它将抛出
ratelimitRejectedException
。每当我们谈论弹性策略时,我们都会提到双方之间的预定义协议,以克服瞬态失败。因此,速率限制器是此故事的服务器端,而重试(反应性策略)是客户端。
如果要在速率限制器中设置
retryafter
标题,那么您可以这样做,然后在重试的
sleepdurationProvider
委派中的客户端上,您可以像如果响应
是delegateresult&lt; httpresponsemessage&gt;
There were multiple questions so let me answer all of them.
1) How to inject logger to a Policy?
You need to use Polly's context for that.
The context is created outside of the policy. It is used as a container to store any arbitrary information
Then it is passed through the
Execute
/ExecuteAsync
callFinally you can use the context in any user delegate (like
onRetry
/onRetryAsync
) to retrieve the passed objectThe
WithLogger
andGetLogger
extension methods2) Does the above rate limiter work in the same way as the retry?
No. The rate limiter is a proactive policy which can be useful to prevent resource abuse. That means it will throw an
RateLimitRejectedException
if the predefined limit is exceeded.Whenever we are talking about resilience strategy we are referring to a predefined protocol between the two parties to overcome on transient failures. So the rate limiter is the server-side of this story whereas the retry (reactive policy) is the client-side.
If you want to set the
RetryAfter
header in your rate limiter then you can do that like thisThen on the client-side inside your retry's
sleepDurationProvider
delegate you can retrieve that value like this if theresponse
is aDelegateResult<HttpResponseMessage>