根据重试计数调整超时持续时间



>我想使用 Polly 执行以下操作: 尝试超时很短的请求。 如果失败,请重试更长的超时时间。

我看到Retry可以访问这样的retryCount

Policy
.Handle<SomeExceptionType>()
.Retry(3, (exception, retryCount, context) =>
{
    // do something 
});

我看到Timeout可以指定intTimeSpan,如下所示:

Policy.Timeout(TimeSpan.FromMilliseconds(2500))

我什至看到您可以将函数传递给超时,如下所示:

Policy.Timeout(() => myTimeoutProvider)) // Func<TimeSpan> myTimeoutProvider

Func选项似乎是最有希望的,但它在哪里可以访问重试计数? 将状态保留在策略之外很诱人,但如果我想以线程安全的方式共享策略,那就很危险了。

有什么建议吗?

您可以使用

Polly Context在执行中涉及的不同策略之间传递状态数据。 Polly Context 的唯一实例随每次 Polly 执行而流动,因此这是完全线程安全的。

有关此技术的更多详细信息,请参阅此博客文章。

例如:

const string RetryCountKey = "RetryCount";
RetryPolicy retryStoringRetryCount = Policy
    .Handle<Exception>()
    .Retry(3, (exception, retryCount, context) =>
    {
        Console.WriteLine("Storing retry count of " + retryCount + " in execution context.");
        context[RetryCountKey] = retryCount;
    });
TimeoutPolicy timeoutBasedOnRetryCount = Policy
    .Timeout(context =>
    {
        int tryCount;
        try
        {
            tryCount = (int) context[RetryCountKey];
        }
        catch
        {
            tryCount = 0; // choose your own default for when it is not set; also applies to first try, before any retries
        }
        int timeoutMs = 25 * (tryCount + 1);
        Console.WriteLine("Obtained retry count of " + tryCount + " from context, thus timeout is " + timeoutMs + " ms.");
        return TimeSpan.FromMilliseconds(timeoutMs);
    });
PolicyWrap policiesTogether = retryStoringRetryCount.Wrap(timeoutBasedOnRetryCount);

(注意:当然这个^可以更简洁。为了最清晰,请在此处列出。

这是一个实时的dotnetfiddle示例。

来自: https://github.com/App-vNext/Polly/wiki/Timeout

int retryCount_ = 0;
Func<TimeSpan> myTimeoutProvider = () => 
    TimeSpan.FromMilliseconds(25*retryCount_);
// Configure variable timeout via a func provider.
Policy
    .Timeout(() => myTimeoutProvider)) // Func<TimeSpan> myTimeoutProvider
    .Retry(3, (exception, retryCount, context) =>
    {
        retryCount_ = retryCount;
        // do something 
    })

或设置类似于中所示的超时:

Policy
    .Handle<SomeExceptionType>()
    .WaitAndRetry(5, retryAttempt => 
        TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) 
    );

更新

您还可以挂接到onTimeoutAsync回调,并不断增加myTimeoutProvider依赖的局部变量。

最新更新