Azure 服务总线的 Azure Function App 延迟重试

Can*_*vas 6 c# cloud azure azureservicebus azure-functions

首先让我解释一下我所拥有的。我自己有一个带有 Azure Function App 的 Azure 服务总线。服务总线设置为使用 SQL 过滤器将特定消息类型推送到特定主题。然后使用我的 Azure Function App,这些将获取最新的消息,然后对其进行处理。

一个基本的例子

1:我向我的 EmailAPI 发送请求

2:EmailAPI 然后将类型为“电子邮件”的新消息推送到服务总线中

3:SQL Filter 然后看到类型是“Email”,并将其放入 Service Bux 中的电子邮件主题中

4:EmailListener Azure Function 监视服务总线并注意到一条新消息

5:收集服务总线消息并处理它(基本上只是使用提供的信息发送电子邮件)

现在假设由于某种原因 SMTP 服务器连接有点中断,有时我们在尝试发送电子邮件 (EmailListener) 时收到 TimeOutException。现在,当抛出异常时,Function App EmailListener 将立即尝试再次发送,无需等待,它只会尝试再次发送。它将总共执行 10 次,然后通知服务总线将消息放入死信队列。

我试图做的是,当引发异常(例如 TimeOutException)时,我们等待 X 时间,然后再尝试再次处理相同的消息。我查看了许多讨论 host.json 的不同帖子并尝试设置这些设置,但这些都不起作用。我找到了一个解决方案,但是该解决方案要求您创建消息的克隆并将其推回服务总线并为其提供延迟的处理时间。如果 Azure 服务总线/功能应用程序可以自行处理重试,我宁愿不实现自己的手动延迟系统。

我遇到的最大问题(这可能取决于我的理解)是谁有错?是服务总线设置来处理重试策略,还是 Azure 函数应用程序来处理 X 次后尝试重试。

我提供了一些代码,但我觉得代码并不能真正帮助解释我的问题。

// Pseudo code
public static class EmailListenerTrigger
{
    [FunctionName("EmailListenerTrigger")]
    public static void Run([ServiceBusTrigger("messages", "email", Connection = "ConnectionString")]string mySbMsg, TraceWriter log)
    {
           var emailLauncher = new EmailLauncher("SmtpAddress", "SmtpPort", "FromAddress");
           try
           {
               emailLauncher.SendServiceBusMessage(mySbMsg);
           }
           catch(Exception ex)
           {
               log.Info($"Audit Log: {mySbMsg}, Excpetion: {ex.message}");
           }
    }
}
Run Code Online (Sandbox Code Playgroud)

参考一: https: //blog.kloud.com.au/2017/05/22/message-retry-patterns-in-azure-functions/(Thread.Sleep似乎不是一个好主意)

参考二: https: //github.com/Azure/azure-functions-host/issues/2192(手动实现重试)

参考三​​: https: //www.feval.ca/posts/function-queue-retry/(这似乎是指我使用主题时的队列)

参考四:Azure服务总线是否可以延迟重试消息?(讨论推迟消息,但随后您需要手动将其从队列/主题中取出。)

sil*_*ent 4

您也许可以通过使用 Durable Functions 来解决您的问题。例如,有一个内置方法CallActivityWithRetryAsync()可以在活动函数抛出异常时重试。

https://learn.microsoft.com/en-us/sandbox/functions-recipes/durable-diagnostics#calling-activity-functions-with-retry

你的流程可能是这样的:

  1. 服务总线触发功能。这个启动了 Orchestrator 功能

  2. 协调器调用您的活动函数(使用上述方法)

  3. 您的电子邮件发送是在活动函数中实现的,可以根据需要抛出异常