在MSMQ中处理有害消息

时间:2014-01-15 17:06:47

标签: c# sql msmq

当前安装程序包括一个Windows服务,它从本地队列中获取一条消息并提取信息并输入我的SQL数据库。根据我的设计

  1. 服务从队列中获取消息。(我在这里使用Peek())。
  2. 将其发送到数据库。
  3. 如果由于某种原因我在将数据保存到数据库时遇到异常,则消息会重新进入队列,这对我来说是可靠的。
  4. 我正在记录错误,以便用户可以知道问题所在并进行修复。
  5. 异常示例:如果在将消息保存到数据库的过程中丢失了DBconnection,那么消息不会丢失,因为它们在队列中。我不会发送,直到我收到来自DB的确认消息是因此,用户可以看到日志,并确保DBconnection存在,并且每件事都是正常的,我们不会丢失队列中的任何消息。

    但是看看另一个场景:我将在队列中获得的消息来自第三方,根据标准架构。架构将保持不变,并且没有任何变化。但我已经看到一些我得到的一些格式化异常,因为它没有提交,所以消息会回到队列中。此时此消息对我来说将是一个瓶颈,因为再次拾取相同的消息并尝试处理消息。每次服务都会提取相同的消息并获得相同的异常。因此,除非删除该消息或将该消息放在队列的最后,否则这将无限循环。

    看着删除消息:截至目前,如果我基于格式异常...那么我可能是错的,因为我将来可能会遇到其他一些例外。

    有没有办法可以将这些消息放回到列表的最后一个队列而不是队列的开头。

    需要一些关于如何进一步行动的建议。

    注意:队列是交易的。

2 个答案:

答案 0 :(得分:1)

据我所知,MSMQ不会自动将消息转储到失败队列。无论哪种方式你处理它,它只是几行代码(比尔,迈克尔,我建议一个失败队列)。就失败队列而言,您可以简单地创建一个名为.\private$\queuename_fail的队列。

Surviving poison messages in MSMQ对于这个确切的主题是一篇不错的文章,最后有一个示例应用和源代码。

private readonly MessageQueue _failQueue;
private readonly MessageQueue _messageQueue;
/* Other code here (cursor, peek action, run method, initialization etc) */

private void dumpToFailQueue(Message message)
{
    var oldId = message.Id;
    _failQueue.Send(message, MessageQueueTransactionType.Single);

    // Remove the poisoned message
    _messageQueue.ReceiveById(oldId);
}

private void moveToEnd(Message message)
{
    var oldId = message.Id;
    _messageQueue.Send(message, MessageQueueTransactionType.Single);

    // Remove the poisoned message
    _messageQueue.ReceiveById(oldId);
}

答案 1 :(得分:0)

如果出现错误,如果在web.config中为WCF服务配置了消息,则将消息置于中毒队列中。此外,如果需要在某段延迟后重新处理消息,则可以配置重试队列。

更新:让我解释一下这个要求。我们需要处理从其他系统发送的少量xml,并且必须将数据插入/更新/删除到数据仓库中。有时,更新请求在创建请求之前被推入队列(由于某些外部系统依赖性)。因此,当拾取更新请求以进行处理时,它会抛出错误(因为数据库中不存在记录),然后将其推入重试队列以在5分钟后处理。在这个时间范围内,如果创建请求被选中进行处理并且成功,则在更新请求执行5分钟后它就成功了(因为现在它找到了要更新的匹配记录)。 在本文中,解释了重试队列所需的配置更改。毒药队列。除了在WCF服务中创建事务性队列和启用事务之外,不需要更改代码。 Poison and Retry message handling with MSMQ using WCF Net.Msmq binding