【问题标题】:How can I get the retry count within a delegate executed through Polly retry policy?如何获取通过 Polly 重试策略执行的委托中的重试计数?
【发布时间】:2018-12-20 23:49:59
【问题描述】:

我正在实施 Polly 以在我的 C# Web 应用程序中重试请求。我的示例代码包含在这篇文章中。代码按预期工作,但传递给 CreateFile() 的最后一个参数(当前硬编码为 0)需要是 retryAttempt 的值。如何在 Execute Action 中获取 retryAttempt 的值?

return Policy
    .Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
    .Or<StorageException>()
    .WaitAndRetry(maxRetryCount, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)))
    .Execute(() => CreateFile(fileContent, containerName, fileName, connectionString, 0));

【问题讨论】:

标签: c# polly retry-logic


【解决方案1】:

Polly 不提供.Execute(...) 重载,其中重试计数是传递给.Execute(...) 的委托的输入参数之一。这是因为重试只是众多 Polly 策略之一,而 .Execute(...) 重载的形式必须对所有策略类型通用。

对于问题中描述的用例,简单地说:

int count = 0;
return Policy
    .Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
    .Or<StorageException>()
    .WaitAndRetry(maxRetryCount, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)))
    .Execute(() => CreateFile(fileContent, containerName, fileName, connectionString, count++));

另一种方法是使用 Polly 的执行范围 Polly.Context:此实例随每次执行而传播,并且可用于执行的所有部分。

重试策略已将重试计数传递给onRetry 委托,因此该策略可以将其捕获到执行范围的Context

var retryPolicyCapturingCountIntoContext =
    Policy
        .Handle<HttpException>(x => x.StatusCode == (HttpStatusCode)429)
        .Or<StorageException>()
        .WaitAndRetry(
            maxRetryCount,
            retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(retryIntervalMs, retryAttempt)),
            onRetry: (response, delay, retryCount, context) =>
            {
                context["retrycount"] = retryCount;
            });

在通过策略执行的委托中,我们可以从Context中选择重试计数(注意处理尚未发生重试的情况):

retryPolicyCapturingCountIntoContext
    .Execute(context =>
    {
        int retryCount = (context.TryGetValue("retrycount", out var retryObject) && retryObject is int count) ? count : 0;
        CreateFile(fileContent, containerName, fileName, connectionString, retryCount);
    }, new Context());

如果您希望避免 context.TryGetValue(...) 防御性代码的干扰,您也可以选择确保在开始执行之前始终初始化 context["retrycount"]

var myContext = new Polly.Context { {"retrycount ", 0} };
retryPolicyCapturingCountIntoContext
    .Execute(
         context => CreateFile(fileContent, containerName, fileName, connectionString, (int)context["retrycount"]),
         myContext);


对于想要在每次重试发生时捕获重试计数的用户,例如日志记录,请参阅Polly retry examples,其中显示了 retryCount 如何作为输入参数传递给 onRetry 委托,可以在政策。更多示例here

对于希望以通用方式捕获用于成功操作的重试总数的用户 - 例如将遥测作为某些通用执行调度基础设施代码的一部分 - 请参阅 these examples in Steve Gordon's blog,它使用 @987654339基于@的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    相关资源
    最近更新 更多