首先让我解释一下我的情况。我有一个Azure Service Bus与Azure功能应用程序。服务总线设置为使用SQL过滤器将特定消息类型推送到特定主题。然后使用我的Azure功能应用程序,这些将获得最新消息,然后进行处理。
一个基本的例子
1:我向EmailAPI发送请求
2:EmailAPI然后将新消息推送到服务总线,其类型为“电子邮件”
3:SQL Filter然后看到类型是“电子邮件”,并被放入Service Bux中的电子邮件主题
4:EmailListener Azure功能监视服务总线并注意到新消息
5:收集服务总线消息并进行处理(基本上只是使用提供的信息发送电子邮件)
现在让我们说出于某种原因,SMTP服务器连接有点坏了,有时我们在尝试发送电子邮件时会收到TimeOutException(EmailListener)。当抛出异常时会发生什么,Function App EmailListener会立即尝试再次发送它,不等待,它只会尝试再次发送它。它将执行此操作总共10次,然后通知服务总线将消息放入死信队列。
我试图做的是当抛出异常(例如TimeOutException)时,我们在尝试再次处理相同的消息之前等待X时间。我看了很多不同的帖子,谈论了host.json并尝试设置这些设置,但这些都没有用。我找到了一个解决方案,但是该解决方案需要您创建消息的克隆并将其推回到服务总线并为其延迟处理时间。如果Azure Service Bus / Function App可以自行处理重试,我宁愿不实现自己的手动延迟系统。
我遇到的最大问题(这可能取决于我的理解)是谁有错?是服务总线设置来处理重试策略还是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?(谈论推迟消息,然后你需要手动将它从队列/主题中取回。)
您可以通过使用持久功能来解决您的问题。例如,内置方法CallActivityWithRetryAsync()
可以在活动函数抛出异常时重试。
你的流程可能是这样的: