有人可以提供有关使用Azure Service Bus OnMessageOptions.AutoRenewTimeout的更多指导 http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.onmessageoptions.autorenewtimeout.aspx
因为我还没有找到关于此选项的大量文档,并且想知道这是否是更新邮件锁定的正确方法
我的用例:
1)消息处理队列的锁定持续时间为5分钟(允许的最大值)
2)消息处理器使用OnMessageAsync消息泵从队列中读取(使用ReceiveMode.PeekLock)长时间运行的处理可能需要10分钟才能处理消息,然后再手动调用msg.CompleteAsync
3)我希望消息处理器自动更新它的锁定,直到预期完成处理(~10分钟)为止。如果在此期间之后还没有完成,则应自动释放锁定。
由于
- 更新
我从未最终获得有关AutoRenewTimeout的更多指导。我最终使用了一个自定义MessageLock类,它根据计时器自动更新消息锁。
查看要点 - https://gist.github.com/Soopster/dd0fbd754a65fc5edfa9
答案 0 :(得分:14)
要处理长消息处理,您应该设置AutoRenewTimeout
== 10分钟(在您的情况下)。这意味着每次LockDuration
到期时,锁定将在这10分钟内更新。
因此,例如,如果LockDuration
为3分钟且AutoRenewTimeout
为10分钟,则每3分钟锁定将自动续订(3分钟,6分钟和9分钟后)并自动锁定消息被消耗后12分钟后发布。
答案 1 :(得分:1)
我和我的工人有同样的问题。即使消息成功处理,由于处理时间过长,服务总线也会删除应用于它的锁,并且消息可以再次接收。其他可用的工作人员接收此消息并再次开始处理它。如果我错了,请纠正我,但在你的情况下,OnMessageAsync会被同一个消息多次调用,你最终将同时处理几个任务。在该过程结束时将抛出MessageLockLost异常,因为该消息未应用锁定。 我用以下代码解决了这个问题。
_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)
{
}
}
自你的帖子以来有几个坐骑,也许你已经解决了这个问题,所以你可以分享你的解决方案。
答案 2 :(得分:0)
就我个人的喜好而言,OnMessageOptions.AutoRenewTimeout对于租约续订选项来说有点太粗糙了。如果将其设置为10分钟,并且无论出于何种原因,该消息仅在10分钟5秒后才为.Complete(),则该消息将再次显示在消息队列中,并由下一个备用Worker以及整个处理将再次执行。这很浪费,也使工作人员无法执行其他未处理的请求。
要解决此问题:
更改您的Worker进程,以验证它刚刚从Message Queue接收到的项目是否尚未被处理。查找存储在某处的成功/失败结果。如果已经处理过,请调用BrokeredMessage.Complete()并继续等待下一个项目弹出。
定期调用BrokeredMessage.RenewLock()-在锁过期之前(例如每10秒)-并将OnMessageOptions.AutoRenewTimeout设置为TimeSpan.Zero。因此,如果处理项目的工作器崩溃,则消息将尽快返回到MessageQueue中,并由下一个备用工作器拾取。