簡體   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