Azure Service Bus:为无法处理消息而实施指数重试策略的最佳方法

时间:2017-09-15 12:54:35

标签: azure service azureservicebus bus azure-servicebus-topics

我一直在以peek模式接收消息,并在处理失败时放弃它们(不是交付)。但是,该消息立即再次可用,并再次收到处理。它再次快速失败,在最大交付后,它已经死了。

有没有办法将主题/订阅配置为在放弃后释放邮件之前等待?最好是以指数方式。

当然,我也可以通过代码获取建议。

3 个答案:

答案 0 :(得分:1)

无法在Service Bus配置中设置指数退避。我遇到了同样的问题,并做了以下工作:

  1. 将邮件出列,并将邮件标记为已收到。
  2. 在try / catch块中执行处理。如果存在异常,请在将来的某个时间点将新邮件排入计划传递。
  3. 我们将Service Bus Message Queue有效负载包装在一个指定传递尝试次数的类中。我们将传递尝试次数乘以常量,然后将该数字添加到当前日期时间以便将来计划传递。在超出我们想要尝试的传递尝试次数之后,我们明确地将该消息写入死信。

答案 1 :(得分:0)

另一个选择是使用MassTransit,它支持Azure Service Bus。

看看它广泛的retry configuration

请注意,MassTransit会在收到消息后有效地在内存中重试,因此您需要适当地调整主题订阅的MaxDeliveryCountMaxAutoRenewDuration设置。

您的配置可能类似于:

var busControl = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
    var host = cfg.Host(serviceBusConnectionString, hst => { });

    cfg.UseMessageRetry(retryConfigurator =>
        RetryConfigurationExtensions.Exponential(retryConfigurator, ...);

    cfg.SubscriptionEndpoint(
        "subscriptionName",
        "topicPath",
        e =>
        {
            e.Consumer<SomeConsumer>();
            // Let MassTransit do the retries
            e.MaxDeliveryCount = 1;
            e.MaxAutoRenewDuration = TimeSpan.FromMinutes(10);
        });
});

答案 2 :(得分:-1)

我也在研究这个主题,并且遇到了Microsoft的RetryExponential类。

  

RetryExponential类

     

命名空间:Microsoft.ServiceBus
  程序集:Microsoft.ServiceBus.dll

     

表示重试策略的实现。每次必须重试消息传递操作时,重试之间的延迟都会以交错的指数方式增长。

     

from django.db import models from django.urls import reverse class Category(models.Model): name = models.CharField(max_length=200, db_index=True) slug = models.SlugField(max_length=200, db_index=True, unique=True) class Meta: ordering = ('name',) verbose_name = 'category' verbose_name_plural = 'categories' def __str__(self): return self.name def get_absolute_url(self): return reverse('shop:product_list_by_category', args=[self.slug]) class Product(models.Model): category = models.ForeignKey(Category, related_name='products', on_delete=True) name = models.CharField(max_length=200, db_index=True) slug = models.SlugField(max_length=200, db_index=True, unique=True) image = models.ImageField(upload_to='products/%y/%m/%d', blank=True) description = models.TextField(blank=True) price = models.DecimalField(max_digits=10, decimal_places=2) stock = models.PositiveIntegerField() available = models.BooleanField(default=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now_add=True) class Meta: ordering = ('-created',) index_together = (('id', 'slug'),) def __str__(self): return self.name