I am currently trying to handle DeadLetterQueue messages.
How can I write a message to a DLQ?
I tried the following:
{
"type": "serviceBus",
"name": "outputSbMsg",
"queueName": "dlq-test",
"connection": "bus",
"accessRights_": "Manage",
"direction": "out"
}
But when I write to mySbMsg, I get the following error:
Cannot directly create a client on a sub-queue. Create a client on the main queue and use that to create receivers on the appropriate sub-queue.
How can I write to a DLQ (preferably using node)?
AFAIK, you can't write an arbitrary message directly to Service Bus DLQ.
This is not related to Azure Functions. Normally, a C# service bus client would
Dequeue a message from a queue.
If message processing fails, it would either throw exception, call BrokeredMessage.Abandon() or BrokeredMessage.DeadLetter().
Each one of those may move the message to DLQ (potentially after several re-tries).
Now, this doesn't change much in the context of C# Azure Functions
You create an in binding which gets a message from a queue.
If processing fails, you throw an exception, or call BrokeredMessage.Abandon() or BrokeredMessage.DeadLetter() explicitly, if needed.
The message is moved to DLQ (potentially after several re-tries).
Now, in Node you don't have BrokeredMessage class. But you can still throw error. If you want the message to move to DLQ after the first error, set the Max Delivery Count property of your service bus queue to 1.
Related
I've been recently having problems with my Service Bus queue. Random messages (one can pass and the other not) are placed on the deadletter queue with the error message saying:
"DeadLetterReason": "Moved because of Unable to get Message content There was an error deserializing the object of type System.String. The input source is not correctly formatted."
"DeadLetterErrorDescription": "Des"
This happens even before my consumer has the chance to receive the message from the queue.
The weird part is that when I requeue the message through Service Bus Explorer it passes and is successfully received and handled by my consumer.
I am using the same version of Service Bus either for sending and receiving the messages:
Azure.Messaging.ServiceBus, version: 7.2.1
My message is being sent like this:
await using var client = new ServiceBusClient(connString);
var sender = client.CreateSender(endpointName);
var message = new ServiceBusMessage(serializedMessage);
await sender.SendMessageAsync(message).ConfigureAwait(true);
So the solution I have for now for the described issue is that I implemented a retry policy for the messages that land on the dead-letter queue. The message is cloned from the DLQ and added again to the ServiceBus queue and for the second time there is no problems and the message completes successfully. I suppose that this happens because of some weird performance issues I might have in the Azure infrastructure. But this approach bought me some time to investigate further.
I have dot net code which read loan-numbers from Azure service queue and calls my API for each loan-number.
This is my code which calls the api
private async Task ProcessMessagesAsync(Message message, CancellationToken token)
{
try
{
string loanNumber = Encoding.UTF8.GetString(message.Body);
_logger.LogInformation($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} LoanNumber:{loanNumber}");
//API CALL HERE
await _apiClient.getResult(loanNumber);
await _queueClient.CompleteAsync(message.SystemProperties.LockToken);
}
catch (Exception ex)
{
//sending failed messages to Dead Letter queue
await _queueClient.AbandonAsync(message.SystemProperties.LockToken);
}
}
Failed loan-numbers are successfully sent to Dead Letter queue. When the server is down or bad request from API response.
I want to call the api after certain duration on the loan-numbers which are in Dead Letter Queue.
Is there any way to convert the messages in Dead Letter queue to active messages after some interval??
I am new to azure. Please help me to resolve the issue.
Thanks in advance.
Is there any way to convert the messages in Dead Letter queue to
active messages after some interval??
Automatically, no. However what you could do is read the messages from dead letter queue and then post them as new message in your main queue.
As far as automating the whole process, one possible solution would be to run a timer triggered Azure Function that reads messages from a dead letter queue periodically and post them in your main queue.
#akhil, it's worth noting that these messages will automatically be re-queued on the main queue until their DeliveryCount exceeds the MaxDeliveryCount of your main queue. The default value for MaxDeliveryCount is 10 so any failed requests to the API be retried ten times by this handler before being moved to the DLQ.
If you wanted to be a bit 'smarter' about this you could delay the retries using the ScheduledEnqueueTimeUtc property on the message in your catch block.
As #Gaurav Mantri has said, the framework offers nothing to process dead-letter messages 'for free'; you'll have to code a handler yourself as you would for a normal queue.
No, there is no way to convert the DLQ message to active message.
you need to process the DLQ and fix the reason as to why it ended in DLQ and then re transmit it back to your queue.
A sample from Github can be useful here.
https://github.com/Azure/azure-service-bus/tree/master/samples/DotNet/Microsoft.ServiceBus.Messaging/DeadletterQueue
(This sample shows how to move messages to the Dead-letter queue, how to retrieve messages from it, and resubmit corrected message back into the main queue.)
This could be an old answer but we can use ServiceBusExplorer from Microsoft. It can pull the messages from dead letter queue and then those can be requeued using
Let me know if you have any further questions.
C# .NetCore 2.2 -
Azure Service Bus 3.4.0
I have 3 queues in Azure Service Bus with same properties. While sending messages to these queues, the messages in one of the queues always get delivered to Dead letter queues, while other 2 queues receive active messages.
I have tried playing with the properties - increase TTL, maximum delivery count etc. The properties of all 3 queues are same, the only difference is the name of the queues.
I have used this tutorial - https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues
queue properties image
static async Task SendMessagesAsync(int numberOfMessagesToSend)
{
try
{
for (var i = 0; i < numberOfMessagesToSend; i++)
{
// Create a new message to send to the queue.
string messageBody = $"Message {i}";
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
Console.WriteLine($"Sending message: {messageBody}");
// Send the message to the queue.
await queueClient.SendAsync(message);
}
}
catch (Exception exception)
{
Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
}
}
How do I prevent messages from going to Dead Letter Queue? Why does it happen with only 1 queue, not the other 2?
When messages are dead-lettered, there is a reason user property gets added. Check that property to see the reason and troubleshoot accordingly. Specifically, check for DeadLetterReason and DeadLetterErrorDescription custom properties.
The common reasons for a message to be dead-lettered are
Maximum transfer hop count exceeded
Session Id Is Null
TTLExpiredException
HeaderSizeExceeded
The messages might also have got dead-lettered due to some errors while receiving the message from the Queue. As Sean Feldman mentioned, looking into the DeadLetterReason and DeadLetterDescription property will help you diagnose the error reason clearly.
Also try to increase or set the time to live of the message sent if the DeadLetterReason is TTLExpiredException. Because if you have set the time to live of the message to a lower value then it will override the time to live property of the Queue.
Check whether the Queue whether the queue where the messages are getting dead-lettered is a Session enabled queue and the message sent has the Session Id value set.
Without seeing your app / messages it's hard to help. But probably there's an error with the application that is trying to consume the message. As it could not be completed, the message goes to the dead letter queue.
Log the messages from this particular queue and see if there's any missing required properties. Sometimes you're trying to deserialize to an uncompatible type.
The purpose of the dead-letter queue is to hold messages that cannot
be delivered to any receiver, or messages that could not be processed.
How can I send message to deadletter queue?
serviceBusService.receiveQueueMessage(MESSAGE_QUEUE, {isPeekLock: true}, (error, message) => {
...... // want to put message to deadletter queue if there is exception
serviceBusService.deleteMessage(message, error => {
});
});
Mostly, you'd want to rely on the system to decide when to move a message to DLQ and make it the messaging engine's responsibility as much as possible (and not explicitly put a message on DLQ.) It also appears that the guidance in this scenario was provided via documentation here: How to handle application crashes and unreadable messages
Looks like you are using the older azure-sb package that relies on the HTTP REST apis. If you instead use the newer #azure/service-bus package which uses the faster AMQP implementation, there is a deadletter() method on the message you receive that you can use to send the message to the dead letter queue.
According to this WebJobs documentation page, for POCO output queue messages, "A queue message is always created, even if the object is null."
In my scenario, I only want to conditionally output queue messages from my WebJob. Currently I am getting a ton of null messages to my downstream WebJob using the "out" queue:
[Queue("myoutqueue")] out myPOCO outputQueueMessage
Is the only way to do this to not use the WebJobs Queue attribute and to queue the message myself using the client library?
You can conditionally enqueue an output message by using the ICollector<T> binding. For example:
[Queue("myoutqueue")] ICollector<MyPoco> outMessages
Then, only messages added to the collector via outMessages.Add(message) will be sent (one or more). More on ICollector<T> and other Queue bindings can be found here.