Guidance OnMessageOptions.AutoRenewTimeout

自古美人都是妖i 提交于 2019-12-03 11:51:50

To handle long message processing you should set AutoRenewTimeout == 10 min (in your case). That means that lock will be renewed during these 10 minutes each time when LockDuration is expired.

So if for example your LockDuration is 3 minutes and AutoRenewTimeout is 10 minutes then every 3 minute lock will be automatically renewed (after 3 min, 6 min and 9 min) and lock will be automatically released after 12 minutes since message was consumed.

I have the very same problem with my workers. Even the message was successfully processing, due to long processing time, service bus removes the lock applied to it and the message become available for receiving again. Other available worker takes this message and start processing it again. Please, correct me if I'm wrong, but in your case, OnMessageAsync will be called many times with the same message and you will ended up with several tasks simultaneously processing it. At the end of the process MessageLockLost exception will be thrown because the message doesn't have a lock applied. I solved this with the following code.

_requestQueueClient.OnMessage(
            requestMessage =>
            {
                RenewMessageLock(requestMessage);
                var messageLockTimer = new System.Timers.Timer(TimeSpan.FromSeconds(290));
                messageLockTimer.Elapsed += (source, e) =>
                {
                    RenewMessageLock(requestMessage);
                };
                messageLockTimer.AutoReset = false; // by deffault is true
                messageLockTimer.Start();

                /* ----- handle requestMessage ----- */

                requestMessage.Complete();

                messageLockTimer.Stop();
            }

 private void RenewMessageLock(BrokeredMessage requestMessage)
    {
        try
        {
            requestMessage.RenewLock();
        }
        catch (Exception exception)
        {

        }
    }

There are a few mounts since your post and maybe you have solved this, so could you share your solution.

To my personal preference, OnMessageOptions.AutoRenewTimeout is a bit too rough of a lease renewal option. If one sets it to 10 minutes and for whatever reason the Message is .Complete() only after 10 minutes and 5 seconds, the Message will show up again in the Message Queue, will be consumed by the next stand-by Worker and the entire processing will execute again. That is wasteful and also keeps the Workers from executing other unprocessed Requests.

To work around this:

  1. Change your Worker process to verify if the item it just received from the Message Queue had not been already processed. Look for Success/Failure result that is stored somewhere. If already process, call BrokeredMessage.Complete() and move on to wait for the next item to pop up.

  2. Call periodically BrokeredMessage.RenewLock() - BEFORE the lock expires, like every 10 seconds - and set OnMessageOptions.AutoRenewTimeout to TimeSpan.Zero. Thus if the Worker that processes an item crashes, the Message will return into the MessageQueue sooner and will be picked up by the next stand-by Worker.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!