【问题标题】:Azure service bus deadletter queue message unable to stay in deadletter for longer timeAzure 服务总线死信队列消息无法在死信中停留更长时间
【发布时间】:2020-10-01 09:14:05
【问题描述】:

我有 Azure Main 函数应用程序,它处理来自服务总线的消息。

如果由于 API 关闭而发生异常,则我将消息推送到死信队列。

我有另一个 azure Dead 函数应用程序,它不断读取 DLQ 并将消息推回主队列。

主函数应用程序检查 api 是否关闭,然后再次将消息推送到 DLQ,这应该一直持续到 API 启动并且主函数应用程序成功处理消息。

但问题是一段时间后消息会自动清除。

我检查了默认消息生存时间是 2 小时 30 分钟,但消息无法在那里停留这么长时间。当我将消息推送回 Main 时,我认为在 Dead Function 应用程序中。主队列中的消息可能被识别为重复但不确定。

对于给定的默认消息生存时间,我应该如何将消息维持到 DLQ?

将消息推回主队列的死信函数应用代码 -

 MessageSender sender = new MessageSender(Environment.GetEnvironmentVariable("ConnectionStringSettingName"), UtilityHelper.GetAndValidateAppSetting("TopicName"), RetryPolicy.Default);

            Message deadLetterMessage = new Message(message.Body);

            foreach (KeyValuePair<string, object> userProperty in message.UserProperties)
            {
                deadLetterMessage.UserProperties.Add(userProperty.Key, userProperty.Value);
            }

            //Send the message to the Active Queue
            await sender.SendAsync(deadLetterMessage);

主要功能应用代码-

[FunctionName("ProcessMessage")]
        public static async System.Threading.Tasks.Task RunAsync([ServiceBusTrigger("mytopic", "mysub", Connection = "ConnectionStringSettingName")]Message mySbMsg, string lockToken, MessageReceiver messageReceiver, ILogger log)
        {
            
            try
            { 
                  log.LogInformation("Process message...");
            }
            catch (Exception ex)
            {
                log.LogInformation($"Send message to dead-letter: {ex}");
                await messageReceiver.DeadLetterAsync(lockToken);
            }
        }

我的逻辑是:在 API 启动之前,我将消息发送到 DLQ 和 DLQ 函数应用程序将其推回主队列,这样我就不会丢失消息。

更新

找出根本原因:

Microsoft.Azure.ServiceBus.ServiceBusCommunicationException:一个 无法对套接字执行操作,因为系统缺少 足够的缓冲区空间或因为队列已满错误代码: NoBufferSpaceAvailable ---> System.Net.Sockets.SocketException: An 无法对套接字执行操作,因为系统缺少 足够的缓冲区空间或因为队列已满 Microsoft.Azure.ServiceBus.ServiceBusConnection.CreateConnectionAsync(时间跨度 超时)

如何解决这个问题?

【问题讨论】:

  • 这个问题在编辑之前处于非常不可读的状态。有不是引号的引号块,不是代码的内联代码格式,以及未标记为更新的上下文更新,被编辑到问题的开头。我觉得这超出了一个仅仅不清楚的问题的普通水平,并且反映了对接近破坏行为的过度格式化的依恋。

标签: c# azure azureservicebus azure-function-app


【解决方案1】:

默认消息生存时间设置不适用于死信。根据documentation:

没有自动清理 DLQ。消息保留在 DLQ 中,直到您从 DLQ 显式检索它们并在死信消息上调用 Complete()。

上述将死信消息返回到原始队列的函数的代码将完成每个死信消息,并且这些消息将从死信队列中消失。

【讨论】:

  • 感谢您的澄清.. 请您帮助实现我的目标.. 我想将该消息保留到 dlq 中。通过使用上面的代码,我将该消息再次扔回主队列以进行处理,如果仍然错误,则在主函数应用程序中再次将其扔回 dlq
  • 说实话,我不太明白你想做什么。 DLQ 不是一个普通的队列。这是一个系统队列。它不能用于“持久化”消息。如果消息是死信,经过第二个函数(重试)函数,并且仍然在 DLQ 中结束,则消息是有毒的,或者存在逻辑问题。
  • 您不会丢失消息,但它可能会随着您的设置进入无限循环。
  • 10 分钟后丢失消息?那是不可能的。要么消息得到处理,要么以某种方式完成。死信消息永远不应该丢失。如果发生这种情况,那将是一个代理错误。
  • 我会在死信消息中添加一个自定义属性,以计算从死信队列中重试了多少次,这是一个从原始消息携带的值,每次消息增加一被送去重新处理。在某个时候,与其重试,不如用它做其他事情(记录、存储某处等)来打破循环。
猜你喜欢
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-07
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 1970-01-01
相关资源
最近更新 更多