0
votes

I use Azure Service Bus Queue to receive message and start a long running activity which can last from couple of minutes to couple of hours. During the activity a separate thread renews lock each 30 secs until activity is complete. On BrokeredMessage.RenewLock(), exception occurred, full trace below: "Microsoft.ServiceBus.Messaging.SessionLockLostException" (This happened for the first time)

Here is the code that renews lock

Timer resetToken = new System.Threading.Timer (e => RenewLockQueueJobMessage (), null, TimeSpan.Zero, TimeSpan.FromSeconds (30));
private void RenewLockQueueJobMessage ()
{
   brokeredMessage.RenewLock ();
 }

Configuration of Queue:

QueueDescription queueDescription = new QueueDescription (queueName);
queueDescription.EnablePartitioning = true;
queueDescription.RequiresSession = true;
queueDescription.RequiresDuplicateDetection = true;
queueDescription.EnableDeadLetteringOnMessageExpiration = true;
queueDescription.DefaultMessageTimeToLive = TimeSpan.MaxValue;
queueDescription.LockDuration = TimeSpan.FromMinutes (1);
var manager = NamespaceManager.CreateFromConnectionString (connectionString);
manager.CreateQueue (queueDescription);

Exception Trace:

Microsoft.ServiceBus.Messaging.SessionLockLostException: Channel:uuid:;Link: TrackingId:, SystemTracker:net.tcp:,  ---> System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]:
   at Microsoft.ServiceBus.Messaging.Sbmp.DuplexRequestBindingElement.DuplexRequestSessionChannel.ThrowIfFaultMessage(Message wcfMessage)
   at Microsoft.ServiceBus.Messaging.Sbmp.DuplexRequestBindingElement.DuplexRequestSessionChannel.HandleMessageReceived(IAsyncResult result)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.ServiceBus.Common.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at 

    Microsoft.ServiceBus.Messaging.Sbmp.DuplexRequestBindingElement.DuplexRequestSessionChannel.EndRequest(IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Channels.ReconnectBindingElement.ReconnectChannelFactory`1.RequestSessionChannel.RequestAsyncResult.<>c.<GetAsyncSteps>b__9_3(RequestAsyncResult thisPtr, IAsyncResult r)
       at Microsoft.ServiceBus.Messaging.IteratorAsyncResult`1.StepCallback(IAsyncResult result)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at Microsoft.ServiceBus.Common.AsyncResult.End[TAsyncResult](IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Channels.ReconnectBindingElement.ReconnectChannelFactory`1.RequestSessionChannel.EndRequest(IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Sbmp.RedirectBindingElement.RedirectContainerChannelFactory`1.RedirectContainerSessionChannel.RequestAsyncResult.<>c__DisplayClass8_1.<GetAsyncSteps>b__4(RequestAsyncResult thisPtr, IAsyncResult r)
       at Microsoft.ServiceBus.Messaging.IteratorAsyncResult`1.StepCallback(IAsyncResult result)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at Microsoft.ServiceBus.Common.AsyncResult.End[TAsyncResult](IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Sbmp.RedirectBindingElement.RedirectContainerChannelFactory`1.RedirectContainerSessionChannel.EndRequest(IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Channels.ReconnectBindingElement.ReconnectChannelFactory`1.RequestSessionChannel.RequestAsyncResult.<>c.<GetAsyncSteps>b__9_3(RequestAsyncResult thisPtr, IAsyncResult r)
       at Microsoft.ServiceBus.Messaging.IteratorAsyncResult`1.StepCallback(IAsyncResult result)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at Microsoft.ServiceBus.Common.AsyncResult.End[TAsyncResult](IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Channels.ReconnectBindingElement.ReconnectChannelFactory`1.RequestSessionChannel.EndRequest(IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Sbmp.SbmpMessageReceiver.RenewLockAsyncResult.<>c.<GetAsyncSteps>b__10_1(RenewLockAsyncResult thisPtr, IAsyncResult a)
       at Microsoft.ServiceBus.Messaging.IteratorAsyncResult`1.StepCallback(IAsyncResult result)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at Microsoft.ServiceBus.Common.AsyncResult.End[TAsyncResult](IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.Sbmp.SbmpMessageReceiver.OnEndRenewMessageLocks(IAsyncResult result)
       --- End of inner exception stack trace ---
       at Microsoft.ServiceBus.Common.ExceptionExtensions.ThrowException(Exception exception)
       at Microsoft.ServiceBus.Common.AsyncResult.End[TAsyncResult](IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.ReceiveContext.EndRenewLock(IAsyncResult result)
       at Microsoft.ServiceBus.Messaging.ReceiveContext.EndRenewLock(IAsyncResult result)
1

1 Answers

0
votes

Your queue requires a session and using partitioned entity. SessionLockLostException will happen sooner or later and you should retry receiving and processing. Message will be picked up again and will be reprocessed by the consumer or another instance if you're scaled out.

Additionally

  1. You could change MaxLockDuration to 5 mins and reduce timer frequency to issue lock renewal.
  2. Consider OnMessage API with auto renewal to simplify lock renewal in your code and exception handling. This sample can help.