我正在研究基于Azure的项目进行一些研究,并且在从CloudQueue实例中删除消息时遇到了一些问题。代码相当简单,所以当我尝试从队列中删除消息时,为什么会抛出异常让我感到有些困惑。
以下是为队列生成数据的代码:
foreach (var cell in scheme(cells))
{
string id = Guid.NewGuid().ToString();
var blob = sweepItemContainer.GetBlobReference(id);
using (BlobStream stream = blob.OpenWrite())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, cell);
}
sweepItemQueue.AddMessage(new CloudQueueMessage(id), new TimeSpan(1, 0, 0));
}
以下是使用队列中数据的代码:
var msgs = sweepItemsQueue.GetMessages(MsgAmt);
foreach (var msg in msgs)
{
_handleMessage(msg, sweepItemsContainer);
sweepItemsQueue.DeleteMessage(msg);
mergeItemsQueue.AddMessage(new CloudQueueMessage(msg.AsString), new TimeSpan(1, 0, 0));
}
我看不到消息如何不存在于队列中。除了其他消费者之外,没有其他东西可以改变队列。但我确信他们不能得到相同的信息(只要时间跨度没有用完),那么这是怎么回事?
答案 0 :(得分:2)
您需要担心两个超时,消息在队列中存在多长时间(您在.AddMessage()
调用中指定的消息以及调用{{1时设置的可见性超时) (默认情况下,这是30秒,有一个overload,允许您指定超时)。当您调用.GetMessages()
时,所有返回的消息对于期间'visibilityTimeout的其他消费者是不可见的'。这段时间结束后,所有其他消费者都无法看到您尚未删除的所有消息。
要检查这是否是问题,我会尝试使用.GetMessages()
的重载,其最大可见性超时为2小时。如果这是问题,您可以将此值微调到更合理的数字。另一种选择是一次只检索一条消息。
答案 1 :(得分:1)
史蒂夫马克思的另一个答案,基本上看看存储异常并继续前进。我也在其他框架中看到了这个: Steve Marx blog post
try
{
q.DeleteMessage(msg);
}
catch (StorageClientException ex)
{
if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound")
{
// pop receipt must be invalid
// ignore or log (so we can tune the visibility timeout)
}
else
{
// not the error we were expecting
throw;
}
}