Azure 服务总线死信队列消息无法在死信中停留更长时间
Azure service bus deadletter queue message unable to stay in deadletter for longer time
我有 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: An
operation on a socket could not be performed because the system lacked
sufficient buffer space or because a queue was full ErrorCode:
NoBufferSpaceAvailable ---> System.Net.Sockets.SocketException: An
operation on a socket could not be performed because the system lacked
sufficient buffer space or because a queue was fullat
Microsoft.Azure.ServiceBus.ServiceBusConnection.CreateConnectionAsync(TimeSpan
timeout)
如何解决这个问题?
默认消息生存时间设置不适用于 dead-letter。根据 documentation:
There's no automatic cleanup of the DLQ. Messages remain in the DLQ until you explicitly retrieve them from the DLQ and call Complete() on the dead-letter message.
上面 returns dead-lettered 消息到原始队列的功能的代码将完成每条 dead-lettered 消息,这些消息将从 dead-letter 中消失排队。
我有 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: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full ErrorCode: NoBufferSpaceAvailable ---> System.Net.Sockets.SocketException: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was fullat Microsoft.Azure.ServiceBus.ServiceBusConnection.CreateConnectionAsync(TimeSpan timeout)
如何解决这个问题?
默认消息生存时间设置不适用于 dead-letter。根据 documentation:
There's no automatic cleanup of the DLQ. Messages remain in the DLQ until you explicitly retrieve them from the DLQ and call Complete() on the dead-letter message.
上面 returns dead-lettered 消息到原始队列的功能的代码将完成每条 dead-lettered 消息,这些消息将从 dead-letter 中消失排队。