繁体   English   中英

我们可以在服务总线主题触发 Azure 函数中使用 Polly 重试而不是 ExponentialBackoffRetry 吗?

[英]Can we use Polly retry instead of ExponentialBackoffRetry in Service Bus Topic Trigger Azure Function?

我们正在使用服务总线主题触发器 Azure 函数,并且我们计划在 Azure 函数中实现一个简单的行为,如果在处理/处理过程中出现任何异常,我们希望将下一次重试推迟一段时间。

目前我们计划使用[ExponentialBackoffRetry]属性,如下面的代码所示。

但是我们可以使用Polly retry 代替[ExponentialBackoffRetry]吗? 基本上哪种方法可以满足我们的要求 - [ExponentialBackoffRetry]Polly重试

下面是我们的服务总线主题触发 Azure 函数:

 [FunctionName(nameof(CardGroupEventSubscriber))]
 [ExponentialBackoffRetry(5, "00:00:04", "00:01:00")]
 public async Task RunAsync([ServiceBusTrigger("%ServiceBusConfigOptions:TopicEventTypeName%", "%ServiceBusConfigOptions:TopicEventTypeSubscription%",
            Connection = "ServiceBusConfigOptions:ConnectionString")]
            string sbMsg)
        {
            try
            {   
                var message = sbMsg.AsPoco<CardGroupEvent>();

                _logger.LogInformation("{class} - {method} - {RequestId} - Start",
                   nameof(CardGroupEventSubscriber), nameof(CardGroupEventSubscriber.RunAsync), message.RequestID);

                _logger.LogInformation($"Started processing message {message.AsJson()} with", nameof(CardGroupEventSubscriber));

                var validationResult = new CardGroupEventValidator().Validate(message);

                if (validationResult.IsValid)
                {
                    await _processor.ProcessAsync(message);
                }
                
            catch (Exception ex)
            {
                _logger.LogError($"Unable to process card group event {sbMsg.AsJson()} with {nameof(CardGroupEventSubscriber)}," +
                    $" ExceptionMessage:{ex.Message}, StackTrace: {ex.StackTrace}");
                throw;
            }
            #endregion

        }

Polly 的策略可以以命令的方式定义和使用。
ExponentialBackoffRetry属性可以被认为是声明性的。

因此,假设您要定义一个策略

  • 使用抖动进行指数回退
  • 仅当抛出CosmosException时,您才可以这样做:
const int maxRetryAttempts = 10;
const int maxDelayInMilliseconds = 32 * 1000;
var jitterer = new Random();
var policy = Policy
  .Handle<CosmosException>()
  .WaitAndRetryAsync(
      maxRetryAttempts,
      retryAttempt =>
      {
          var calculatedDelayInMilliseconds = Math.Pow(2, retryAttempt) * 1000;
          var jitterInMilliseconds = jitterer.Next(0, 1000);

          var actualDelay = Math.Min(calculatedDelayInMilliseconds + jitterInMilliseconds, maxDelayInMilliseconds);
          return TimeSpan.FromMilliseconds(actualDelay);
      }
  );
  • 我自己在这里实现了指数退避
    • 主要原因是减少包的数量(所以,我们不需要Polly.Contrib.WaitAndRetry

现在让我们将其应用于您的RunAsync方法

[FunctionName(nameof(CardGroupEventSubscriber))]
public async Task RunAsync([ServiceBusTrigger("%ServiceBusConfigOptions:TopicEventTypeName%", "%ServiceBusConfigOptions:TopicEventTypeSubscription%",
    Connection = "ServiceBusConfigOptions:ConnectionString")]
    string sbMsg)
  => await GetExponentialBackoffRetryPolicy.ExecuteAsync(
        async () => await RunCoreAsync(sbMsg));

public async Task RunCoreAsync(string sbMsg)
{
    try
    ...
}
  • 我已将原始RunAsync的代码移动到RunCoreAsync方法中
  • 我已将RunAsync实现替换为一个创建上述策略然后装饰RunCoreAsync

附带说明:在 CosmosDb 的情况下,以不同的方式处理速率限制/节流可能是有意义的。

当我收到CosmosException并且StatusCode是 429 然后使用RetryAfter的值来延迟重试,就像这样

var policy = Policy
    .Handle<CosmosException>(ex => ex.StatusCode == HttpStatusCode.TooManyRequests)
    .WaitAndRetryAsync(maxRetryAttempts,
       sleepDurationProvider:(_, ex, __) => ((CosmosException)ex).RetryAfter.Value,
       onRetryAsync: (_, __, ___, ____) => Task.CompletedTask);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM