0

我们有一个 WCF 服务,用于侦听队列 (MSMQ) 上的消息。它向我们的 Web 服务器 (REST API) 发送一个请求,该服务器返回一个 HTTP 状态代码。

如果状态码在 400 范围内,我们将丢弃该消息。这个想法是 400 范围错误永远不会成功(未经授权、错误请求、未找到等),因此我们不想继续重试。

对于所有其他错误(例如,500 - 内部服务器错误),我们将 WCF 配置为将消息放在“重试”队列中。重试队列上的消息会在一定时间后重试。这个想法是服务器暂时关闭,所以等待并重试。

WCF 的设置方式,如果我们FaultException在服务契约中抛出一个,它会自动将消息放到重试队列中。

当消息导致 400 范围错误时,我们只是在吞下错误(我们只是记录它)。这可以防止重试机制触发;但是,最好将消息移动到死信队列。这样,我们可以通过向用户和/或系统管理员发送电子邮件来对错误做出反应。

有没有办法立即将这些坏消息移动到死信队列?

4

2 回答 2

1

首先,我一直提到死信队列。在我发布这个问题时,我不知道 WCF/MSMQ 会自动创建所谓的毒子队列。任何无法在配置的次数内传递的消息都被放入毒子队列中。

在我的情况下,我知道有些消息永远不会成功,所以我想立即将消息移出队列。

解决方案是创建第二个队列,我称之为“毒药”(不要与毒药子队列混淆)。我的 catch 块将创建一个 WCF 客户端实例并将消息转发到此毒物队列。我可以重用同一个客户端来发布到原始队列和毒队列;我只需要在每个配置文件中创建一个单独的客户端端点。

我运行了两个单独ServiceHost的实例来读取队列。当ServiceHost发生不可恢复的错误时,原始队列执行 HTTP 请求并将消息转发到毒队列。第二个ServiceHost将简单地发送一封电子邮件以记录消息丢失。

还有超过最大尝试次数的临时错误的问题。WCF/MSMQ 自动创建一个名为<myqueuename>;poison. 您不能通过 WCF 直接写入子队列,但可以使用ServiceHost. 每当消息最终进入毒子队列时,我只需将消息转发到毒子队列,使用与我在原始处理程序的 catch 块中使用的完全相同的客户端。

我希望能够在错误电子邮件中包含堆栈跟踪。由于我为所有处理程序重用相同的客户端和服务合同,我不能只将堆栈跟踪作为字符串传递(除非我将它添加到我的所有数据合同中)。相反,我让毒物处理程序再次尝试执行代码,这将再次失败并吐出堆栈跟踪。

这就是我的消息队列最终的样子:

MyQueue
    - Queue messages
    - Retry
    - Poison
MyQueuePoison
    - Queue messages

这种方法相当复杂。从 WCF 服务处理程序中调用 WCF 客户端很奇怪。这也意味着在服务器上再设置一个队列和大量额外的配置部分,用于指定客户端应该将消息转发到哪个队列。

于 2015-03-11T19:58:39.677 回答
0

希望我已经理解了您的问题,如果这是我认为您所说的,那么是的,但是您显然需要对其进行编程才能做到这一点。但是您确实需要设置重试量,以便 MSMQ 可以重试直到放弃。或者您可以为死信/消息创建自己的自定义队列

http://msdn.microsoft.com/en-us/library/ms789035(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/ms752268(v=vs.110) .aspx

也看看这里:

http://www.michaelfcollins3.me/blog/2012/09/20/wcf-msmq-bad-message-handling.html

如何处理 WCF 的 MSMQ 绑定中的消息失败

我希望这些链接有所帮助。

于 2014-05-30T19:11:05.833 回答