我有一个辅助角色,它使用Azure队列中的消息在后台进行一些处理。 当我检查我的日志时,在处理消息时似乎没有记录异常,但仍然在我的日志中我得到以下异常(仅从长错误日志中粘贴一些相关文本):
System.Net.WebException Microsoft.WindowsAzure.Storage.StorageException异常消息: 远程服务器返回错误:(404)Not Found。遥控器 服务器返回错误:(404)未找到。堆栈痕迹:at System.Net.HttpWebRequest.GetResponse()at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync [T](RESTCommand
1 cmd, IRetryPolicy policy, OperationContext operationContext) --- Next Call Stack: at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand
1 cmd,IRetryPolicy策略,OperationContext operationContext)at Microsoft.WindowsAzure.Storage.Queue.CloudQueue.DeleteMessage(字符串 messageId,String popReceipt,QueueRequestOptions选项, OperationContext operationContext)at InnovativeExams.Azure.CloudStorage.AzureQueue`1.DeleteMessage(T message)指定的消息不存在。 ErrorCode:MessageNotFound Prod-WorkerError Context
以下是我在工作角色中的代码:
private void ProcessQueueMessage(object queueMessageToProcess)
{
var queueMessage = queueMessageToProcess as EventCompletedQueueMessage;
try
{
if (_eventCompletedProcessor.Process(queueMessage))
_azureQueue.DeleteMessage(queueMessage);
}
catch (Exception ex)
{
_logger.LogError(string.Format("Event Completed message <{0}> was not processed due to an exception", queueMessage.Id), ex, LogSources.WorkerRole_EventCompletedDispatcher);
}
}
上述异常会在上面的catch块中捕获并记录。
我认为当worker角色尝试删除队列中的消息并且找不到消息时会出现问题。
需要某人的帮助才能帮助我解决此错误并了解背景中出现的问题。
评论中提出的问题很少:
1)您是否正在运行工作者角色的多个实例?
答:这是一个现有的应用程序,我发现我们正在使用 ThreadPool 来预先实例化,这些线程已准备就绪。
2)你好吗&#34;得到&#34;你的工作者角色中的消息?您是否正在使用某种领导者选举模式来决定哪个实例获取消息?
答:是的,有一个框架可以确定要处理的QueueMessage的相应调度程序。
3)当您收到消息时,这些消息的可见性超时是什么?
答:它设定为120.
4)您需要多长时间处理这些消息,即获取消息和删除消息之间需要多长时间?
答:我不确定。
答案 0 :(得分:2)
让我解释一下,在什么情况下你会得到你遇到的错误。
当您将消息出列队列(即Azure术语中的GET Messages
)时,Azure队列服务会返回名为popreceipt
的内容,该内容必须用于删除或更新消息。这个popreceipt
是一个不透明的值(即你不应该在它周围构建任何业务逻辑),它在相同的消息再次出列之前一直有效。当邮件再次出列时,您将获得popreceipt
的新值,您应该使用此新值来删除或更新邮件。
如果您尝试使用旧的popreceipt
值来删除邮件,而邮件再次出列(通过其他一些过程),您将收到错误。
我的猜测是,这就是你的应用程序中发生的事情。请检查是否确实如此:
其中一个辅助角色实例使消息出列并开始处理该消息。根据您上面所说的内容,您在消息出列时隐藏消息120秒。我假设处理消息所花费的实际时间超过120秒,因此消息重新出现在队列中。现在有另一个进程将此消息出列(因此您获得了新的popreceipt
)。但是,在第二个进程将消息出列后不久,第一个进程就完成了对消息的处理,现在它想要使用它所拥有的popreceipt
来删除消息。由于此popreceipt不再有效,因此使用此popreceipt对该消息执行删除操作的任何尝试都将导致找不到消息错误。