首先让我解释一下我所拥有的。我自己有一个带有 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}");
}
}
}
引用一: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/ (这似乎是指我使用主题时的队列)
引用四:Can the Azure Service Bus be delayed before retrying a message? (讨论推迟消息,但随后您需要手动将其从队列/主题中取出。)
最佳答案
您也许可以通过使用 Durable Functions 来解决您的问题。例如,有一个内置方法 CallActivityWithRetryAsync()
,可以在事件函数引发异常时重试。
你的流程可能是这样的:
服务总线触发的功能。这会启动 Orchestrator 功能
编排器调用您的事件函数(使用上述方法)
- 您的电子邮件发送是在事件函数中实现的,可以根据需要抛出异常
关于c# - Azure 服务总线的 Azure Function App 延迟重试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55937487/