Azure Service Bus BrokeredMessage已被使用?

时间:2012-09-06 21:09:57

标签: azure servicebus azureservicebus

我遇到Azure Service总线的间歇性问题。偶尔,在总线上放置一条消息会导致以下异常:

TYPE:InvalidOperationException

消息:无法执行操作,因为已经消耗了代理消息“723eab13dab34351a78bb687d0923b89”。请使用新的BrokeredMessage实例进行操作。

栈跟踪

at Microsoft.ServiceBus.Messaging.MessagingUtilities.ValidateAndSetConsumedMessages(IEnumerable`1 messages)
at Microsoft.ServiceBus.Messaging.MessageSender.Send(TrackingContext trackingContext, IEnumerable`1 messages, TimeSpan timeout)
at Microsoft.Practices.TransientFaultHandling.RetryPolicy.<>c__DisplayClass1.<ExecuteAction>b__0()
at Microsoft.Practices.TransientFaultHandling.RetryPolicy.ExecuteAction[TResult](Func`1 func)
at IQ.IR.Core.ServiceBus.AzureBus`1.Enqueue(T message) in c:\BuildAgent\work\cc0c51104c02a4e9\IQ.IR.Core\ServiceBus\AzureBus.cs:line 69
...Rest of stacktrace snipped as it's within my app

AzureBus的违规代码是:

public void Enqueue(T message)
{
    using (var brokeredMessage = new BrokeredMessage(message) { Label = message.GetType().FullName, TimeToLive = _timeToLive })
    {
        _retryPolicy.ExecuteAction(() => _sender.Send(brokeredMessage));
    }
}

传入的T消息是

[Serializable]
public class ValidationMessage
{
    public string ValidationToken { get; set;}
}

_retryPolicy是

RetryPolicy<ServiceBusTransientErrorDetectionStrategy>

_timeToLive是12小时的时间跨度

有什么想法吗?

4 个答案:

答案 0 :(得分:5)

错误表示邮件已“已发送”,但过程中出错。遗憾的是,通过检查消息并没有简单的方法来了解这一点,并且消息不能再被重新使用,因为它被认为是消耗的。我们正在进行一些改进,例如允许您查询此类消息的状态并抛出MessagingException而不是InvalidOperation。最后,克隆消息的能力将有助于使这种故障更容易恢复。

答案 1 :(得分:5)

....并继续回答Abhishek的回答:现在你需要为每次重试构建一个新的BrokeredMessage,所以你的重试策略范围需要进一步提升。请记住,如果你输入一个流,我们将在代理消息中使用该流,并将其直接拉到线上,因此您需要提前复制流以进行重试循环。

答案 2 :(得分:1)

即使出现错误,是否可能已发送消息?在这种情况下尝试重试之前,该消息是否应该是幂等的?

答案 3 :(得分:1)

我最近遇到了这个问题,并发现了另一个原因:如果您正在构造BrokeredMessage并设置一个断点,然后再与MessageSender发送它,并检查Message上的属性,它将尝试访问Queue并抛出该消息例外。仅在不检查IDE中其属性的情况下先发送消息就不会导致此问题。