I have an azure function monitoring an Azure service bus queue with default lock duration of 30 seconds. This azure function sends out email notifications based on the user information in the message coming from the queue.
I noticed duplicate emails going out and thus checked the trace logs to find out that azure function has been invoked twice for the same user. Log entries are as follows:
2018-08-09T14:38:05.1249371Z - Executing 'AzureFunction' (Reason='New ServiceBus message detected on 'servicebusqueue'.', Id=4657012a-94ac-4b22-a628-2e94285aeeb7)
2018-08-09T14:38:33.3335833Z - Executing 'AzureFunction' (Reason='New ServiceBus message detected on 'servicebusqueue'.', Id=3ff8eea3-9b9b-43ae-a797-5acf01c2ae6c)
The message was added only once to the queue and I am trying to understand what could generate the other one. Can it be because of the lock duration?
Yes it could be due to the lock duration. The message will be completed (received and deleted) from the Queue, only after the execution of the function is complete. If the execution time exceeds 30 seconds, the message will be unlocked, making it available for any other receivers.
In your case, the receiver would be the same Azure Function, which reads the message another time, that's why you are seeing duplicated processing of the message.
The maximum value of Lock Duration is 5 minutes. If the Azure Function just sends an email notification when the message is received, you can increase the lock duration to 5 minutes. The email transmission shouldn't take that long, so that the message will not be available for another receiver.
If you have plans to add something to the Azure Function in addition to sending the notification, you can set auto renewal for the lock in Azure Function, check here for more details. This will keep the message locked, leaving no option for duplication.
Messages added only once, but it's at-least-once delivery guarantee with PeekLock.
If your message was not successfully completed within 30 seconds from receiving, it will be unlocked and recieved again. Increasing lock duration or reducing processing time should address it.
Related
I am looking into setting up a web job trigger to read message from service bus queue. What would be the best practice to implement a retry logic in case of any errors handling the downstream systems.
Would we be able to throw an exception so that the message will not be deleted from the queue and will be retried after certain time period?
Appreciate your feedback.
You don't need to define retry logic explicitly. When the message is de-queued from service bus , it gets invisible from queue for certain time period (lock time default 30secs , you can configure it). You try to process the message , if it gets successful you simply call BrokeredMessage.CompleteAsync which means i am done and mark this message as completed. If you have some problem in down stream you can abandon the message by calling BrokeredMessage.AbandonAsync . This will unlock the message and the message appears back in the queue. The message will be picked up by the worker again and process it. Until you get successful or reach the max retry limit after which the message is send to dead letter queue.
I am working on Azure Service Bus. My service bus queue is processing one message 3 times. My lock time of message is 5 minutes. Every message is processing max of 2 mins but I don't know why the queue is picking same message and sending to processing and the duplicate messages are picking after 5 mins only.
How can I resolve this?
With Azure Service Bus messages will be re-processed when a message is not actioned by the receiving party. An action would be completing, deferring, dead-lettering. If you don't have any of those, once LockDuration on the broker side expires, the message will be re-delivered. Additional situation when a message would be re-delivered without waiting for LockDuration to time out would be to abandon a message. Then a message is picked up right away by the next request for new messages.
You should share your code to provide enough context. Messages can be received manually using MessageReceiver.ReceiveAsync() or using user-callback API. For the first option you have to action messages (complete for example). For the other option, there's a configuration API where you could opt-out of auto-completion and would be required manually complete message passed into user-callback.
On Azure (or from VS) the dialog for creating new messages inside a queue says the message expires in 7 days, yet it is gone in less than a few seconds. Why? (I created a continuous running WebJob as described in this article)
The message disapear because it has been consummed by your Web job.
The retention delay means you have X days to consume the message (in your case, 7 days). After the delay expired, the message is automatically deleted.
If you want multiple consumer for your messages, instead of a queue, you can use Service Bus with subscription or topics, or Event Hub with consumer groups.
The messages stay in the Service Bus Queue or Topic subscription until they are processed i.e received in receive and delete mode by the receiver.
The message will not be removed from the queue if it is received in peek lock mode.
In your case as the message is processed by the webjob it was not available in the queue.
The messages also have default time to live property which can be set after which the message will be moved to the dead letter path of the same messaging entity(queue or topic subscription).The messages after the given time duration in time to live after scheduled enwueued time utc will be moved to the dead letter path with dead letter reason TTLExpiration
Sometimes there are some messages in Azure Queues that are not taken in charge by Azure Functions and also are not visible from StorageExplorer.
These messages are created without any visibility delay.
Is there any way to know what do those messages contain, and why are they not processed by our Azure Functions?
In the image you can see that we have a message in queue but it is not visible in the list and it is there from hours.
The Azure Queue API currently has no way to check invisible messages.
There are several situations in which a message will become invisible:
The message was added with an VisibilityTimeout in the Put Message request. The message will be invisible until this initial timeout expires.
The message has been retrieved (dequeued). Whenever a message is retrieved it will be invisible for the duration of the VisibilityTimeout specified by the Get Messages request, or 30 seconds by default.
The message has expired. Messages expire after 7 days by default, or after the MessageTTL specified in the Put Message request. Note: after a while these messages are automatically deleted, but until that point they are there as invisible message.
Use cases
Initial VisibilityTimeout
Messages are created with an initial VisibilityTimeout so that the message can be created now, but processed later (after the timeout expires), for whatever reason the creator has for wanting to delay this processing.
VisibilityTimeout on retrieving
The intended process for processing queue messages is:
The application dequeues one or more messages, optionally specifying the next VisibilityTimeout. This timeout should be bigger than the time it takes to process the message(s).
The application processes the message(s).
The application deletes the messages. When the processing fails the message(s) are not deleted.
Message(s) for which the process failed will become visible again as soon as their VisibilityTimeout expires, so that they can be re-tried. To prevent endless retries step 2. should start by checking the DequeueCount of the message: if it is bigger than the desired retry-count it should be deleted, instead of processed. It is good practice to copy such messages to a deadletter / poison queue (for example a queue with the original queue name plus a -poison suffix).
MessageTTL
By default messages have a time-to-live of 7 days. If the application processing cannot handle the amount of messages being added, a backlog could build up. Adjusting the TTL will determine what happens to such backlog.
Alternatively the application could crash, so that the backlog would build up until the application would be started again.
It seems that the message is expired. The following steps could reproduce the issue, you could test it.
Add message with a short TTL
After the message has been expired
I am using the Microsoft Azure ServiceBus for Queue messages using WCF for the subscriptions. I am trying to implement retry logic. I use Peak/Lock to view the message and then have to do some local processing on the message. If that processing fails, I unlock the message so I can try processing it again. The problem is I need to build a have a delay in-between processing tries. Currently it is popped back into the queue and then is processed almost immediately. There needs to be about 2 minutes between attempts.
If you always have to wait 2 minutes before re-processing the message of that particular queue, you could try to configure the lock-timeout on the queue to be 2 minutes (plus the time you expect it will take you to process the message) and then just let the lock expire, instead of unlocking it. This has the downside that you would need to keep an eye on your processing time, and extend the lock's timeout if needed.
Another option could be to receive and complete the message, set a scheduled delivery of 2 minutes into the future, and re send the message. This has the downside that you need to consume it and ack it, which involves certain risks (e.g. your process dies before you get a chance to re-send the message).
"If the message is Peeked in Peek Lock mode from a Queue then you don't have the receive context in the message. You can receive the message in Peek Lock mode, which will lock the message for the interval specified for the 'lock duration' property of the queue. Locked messages cannot be received until its lock expires. Thus, by setting the lock duration to 2 minutes and Receiving messages in Peek Lock mode will solve this issue.
You can either write custom code to update the Lock Duration property. Tools like Service Bus Explorer, Serverless360 etc provides options to update property using graphical user interface."