简体   繁体   English

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

[英]Azure Function App delay retry for azure service bus

First let me explain what I have.首先让我解释一下我有什么。 I have myself an Azure Service Bus with an Azure Function App.我自己有一个带有 Azure Function App 的 Azure 服务总线。 The Service Bus is setup to use SQL Filters to push specific message types into specific topics.服务总线设置为使用 SQL 过滤器将特定消息类型推送到特定主题。 Then using my Azure Function App these will get the newest message and then process it.然后使用我的 Azure Function App,这些将获取最新消息并进行处理。

A basic example一个基本的例子

1: I send a request to my EmailAPI 1:我向我的 EmailAPI 发送请求

2: EmailAPI then pushing a new message into the Service Bus with a type of "Email" 2:EmailAPI 然后将类型为“Email”的新消息推送到服务总线

3: The SQL Filter then sees the type is of "Email" and is placed into the email Topic in the Service Bux 3:SQL Filter然后看到类型是“Email”,并被放入Service Bux中的email Topic

4: The EmailListener Azure Function monitors the Service bus and notices a new message 4:EmailListener Azure Function 监控服务总线并通知新消息

5: Gather the Service Bus message and process it (basically just send the email using the information provided) 5:收集服务总线消息并处理它(基本上只是使用提供的信息发送电子邮件)

Now let's say for some reason the SMTP server connection is a little broken and some times we get a TimeOutException when attempting to send the email (EmailListener).现在假设由于某种原因 SMTP 服务器连接有点中断,有时我们在尝试发送电子邮件 (EmailListener) 时收到 TimeOutException。 What happens now when an exception is thrown, the Function App EmailListener will attempt to send it again instantly, no wait, it will just attempt to send it again.当抛出异常时会发生什么,Function App EmailListener 将尝试立即再次发送,不用等待,它只会尝试再次发送。 It will do this for a total of 10 times and then inform the Service Bus to place the message in the Dead Letter queue.它将总共执行 10 次,然后通知服务总线将消息放入死信队列。

What I am attempting to do is when an exception is thrown (such as TimeOutException), we wait X amount of time before attempting to process the same message again.我试图做的是当抛出异常(例如 TimeOutException)时,我们等待 X 时间,然后再尝试处理相同的消息。 I have looked around at many different posts talking about the host.json and attempting to set those settings, but these have not worked.我看了很多不同的帖子,谈论 host.json 并尝试设置这些设置,但这些都没有用。 I have found a solution, however the solution requires your to create a clone of the message and push it back into the Service Bus and give it a delayed process time.我找到了一个解决方案,但是该解决方案要求您创建消息的克隆并将其推回服务总线并延迟处理时间。 I would prefer not to implement my own manual delay system, if Azure Service Bus / Function App can deal with retries itself.如果 Azure 服务总线/功能应用程序可以自行处理重试,我宁愿不实施我自己的手动延迟系统。

The biggest issue I am having (which is probably down to my understanding) is who is at fault?我遇到的最大问题(这可能取决于我的理解)是谁的错? Is it the Service Bus settings to handle the Retry Policy or is it the Azure Function App to deal with attempting to retry after X time.是处理重试策略的服务总线设置,还是处理 X 时间后尝试重试的 Azure Function App。

I have provided a some code, but I feel code isn't really going to help explain my question.我提供了一些代码,但我觉得代码并不能真正帮助解释我的问题。

// 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}");
           }
    }
}

reference one: https://blog.kloud.com.au/2017/05/22/message-retry-patterns-in-azure-functions/ (Thread.Sleep doesn't seem like a good idea)参考一: https ://blog.kloud.com.au/2017/05/22/message-retry-patterns-in-azure-functions/(Thread.Sleep 似乎不是个好主意)

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

reference three: https://www.feval.ca/posts/function-queue-retry/ (This seems to refer to queues when I am using topics)参考三: https ://www.feval.ca/posts/function-queue-retry/(这个好像是我用topics的时候指的队列)

reference four: Can the Azure Service Bus be delayed before retrying a message?参考四: Azure Service Bus 能否延迟重试一条消息? (Talks about Defering the message, but then you need to manually get it back out the queue/topic.) (谈论推迟消息,但随后您需要手动将其从队列/主题中取出。)

You might be able to solve your issue with the use of Durable Functions.您或许可以通过使用持久函数来解决您的问题。 There is for example a built-in method CallActivityWithRetryAsync() that can retry when the activity functions throws an exception.例如,有一个内置方法CallActivityWithRetryAsync()可以在活动函数抛出异常时重试。

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

Your flow would probably something like this:你的流程可能是这样的:

  1. Service Bus triggered Function.服务总线触发功能。 This one starts an Orchestrator Function这个启动了一个 Orchestrator 函数

  2. The orchestrator calls your activity function (using the aforementioned method)编排器调用您的活动功能(使用上述方法)

  3. Your email sending is implemented in an Activity Function and can throw exceptions as needed您的电子邮件发送是在 Activity Function 中实现的,并且可以根据需要抛出异常

While there is no native support for what you want to do, it is still doable without having to do a lot of custom development.虽然没有对您想做的事情的本机支持,但无需进行大量自定义开发即可实现。 You can basically add a service bus output binding to your Azure function, that is connected to the same queue your function consumes messages from.您基本上可以将服务总线输出绑定添加到您的 Azure 函数,该函数连接到您的函数从中使用消息的同一队列。 Then, use a custom property to track the number of retries.然后,使用自定义属性来跟踪重试次数。 The following is an example:下面是一个例子:

private static TimeSpan[] BackoffDurationsBetweenFailures = new[] { }; // add delays here

[FunctionName("retrying-poc")]
public async Task Run(
  [ServiceBusTrigger("myQueue")] Message rawRequest,
  IDictionary<string, object> userProperties,
  [ServiceBus("myQueue")] IAsyncCollector<Message> collector)
{
  var request = GetRequest(rawRequest);
  var retryCount = GetRetryCount(userProperties);
  var shouldRetry = false;

  try
  {
    await _unreliableService.Call(request);
  }
  catch (Exception ex)
  {
     // I don't retry if it is a timeout, but that's my own choice.
    shouldRetry = !(ex is TimeoutException) && retryCount < BackoffDurationsBetweenFailures.Length;
  }

  if (shouldRetry)
  {
    var retryMessage = new Message(rawRequest.Body);
    retryMessage.UserProperties.Add("RetryCount", retryCount + 1);
    retryMessage.ScheduledEnqueueTimeUtc = DateTime.UtcNow.Add(BackoffDurationsBetweenFailures[retryCount]);
    await collector.AddAsync(retryMessage);
  }
}


private MyBusinessObject GetRequest(Message rawRequest)
  => JsonConvert.DeserializeObject<MyBusinessObject>(Encoding.UTF8.GetString(rawRequest.Body));

private int GetRetryCount(IDictionary<string, object> properties)
  => properties.TryGetValue("RetryCount", out var value) && int.TryParse(value.ToString(), out var retryCount)
            ? retryCount
            : 0;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有办法可以延迟Azure功能中对服务总线消息的重试? - Is there a way I can delay the retry for a service bus message in an Azure function? Azure功能应用程序,服务总线和退货服务总线 - Azure function app, service bus and return service bus Azure Function中的Azure Service Bus - Azure Service Bus in Azure Function 在TaskCancelationException上重试Azure服务总线消息 - Azure Service Bus message retry on TaskCancelationException Azure 服务总线重试选项不起作用 - Azure Service Bus Retry Options Not Working Azure Function App Azure 服务总线触发器触发两次 - Azure Function App Azure Service Bus trigger triggers twice Azure Service Bus和Azure功能队列触发器 - Azure Service Bus and Azure Function Queue Trigger 我们可以在服务总线主题触发 Azure 函数中使用 Polly 重试而不是 ExponentialBackoffRetry 吗? - Can we use Polly retry instead of ExponentialBackoffRetry in Service Bus Topic Trigger Azure Function? 在使用服务总线作为触发器的 C# Azure Function 4.x 中实现指数重试的最佳方法是什么? - What is the best way to implement exponential retry in C# Azure Function 4.x with a Service Bus as a trigger? 我无法重试 Azure 服务总线主题中的失败项目 - I can't retry failed item in Azure Service Bus topic
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM