我正在运行Web函数类型服务总线触发器。
根据情况,我需要放弃该消息并将其放回队列。但是,我只能在 30 秒后再次运行它。我已经配置了主机.json根据 MS文档,但是没有效果。
遵循代码
主机.json
"version": "2.0",
"extensions": {
"serviceBus": {
"clientRetryOptions": {
"mode": "exponential",
"maxRetries": 2,
"delay": "00:00:30.00",
"tryTimeout": "00:01:00",
"maxDelay": "00:01:00"
},
"maxMessageBatchSize": 2
}
}
}
功能
using Azure.Messaging.ServiceBus;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
namespace Teste;
public class FTeste
{
private readonly ILogger _logger;
public FTeste(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<FTeste>();
}
[Function("F_Testes")]
public async Task RunAsync([ServiceBusTrigger("q_teste", Connection = "ServiceBusConnection", IsBatched = true)]
ServiceBusReceivedMessage[] messages,
ServiceBusMessageActions messageActions)
{
foreach (var message in messages)
{
try
{
_logger.LogInformation($"Executou: {message.Body} às {DateTime.Now}");
if (message.Body.ToString().Contains("erro"))
{
await messageActions.AbandonMessageAsync(message);
_logger.LogInformation($"{message.Body} voltou para a fila às {DateTime.Now}");
}
}
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
}
}
}
}
当我执行它时,它放弃的消息(带有错误)返回到队列,但它随后立即再次执行,不遵守文件配置(延迟)30秒。
类似于重试(最大重试次数),它按照 Azure 面板中的配置执行(5),而不是按照主机.json
任何想法?
答案1
我的理解是,clientRetryOptions 将适用于函数实例与服务总线的交互,并用于瞬态故障处理,这与通过触发器缩放控制器进行的函数实例无关。
因此,从逻辑上讲,您的方案只有在将函数设置为单例时才会起作用,否则当您放弃消息时,该函数的另一个实例将能够立即拾取消息(因为锁已被释放),直到允许的最大[重新传递]尝试次数。有一些社区文章可以帮助您将函数设置为单例。
我想,作为使用单例函数的替代方法,您还可以考虑在错误条件下让线程等待/延迟 30 秒,然后再“放弃”消息,只要您在锁上剩余那么多时间,这就可以正常工作 - 但这感觉有点“黑客”。