简体   繁体   English

MSMQ + WCF-立即将邮件移到按字母顺序排列的队列中

[英]MSMQ + WCF - Immediately Move Messages to the Dead-Letter Queue

We have a WCF service that listens for messages on a queue (MSMQ). 我们有一个WCF服务,用于侦听队列(MSMQ)上的消息。 It sends a request to our web server (REST API), which returns an HTTP status code. 它将请求发送到我们的Web服务器(REST API),该服务器返回HTTP状态代码。

If the status code falls within the 400 range, we are throwing away the message. 如果状态代码在400范围内,则我们将丢弃该消息。 The idea is a 400 range error can never succeed (unauthorized, bad request, not found, etc.) and so we don't want keep retrying. 这个想法是400范围的错误永远不会成功(未经授权,错误的请求,未找到等),因此我们不希望继续重试。

For all other errors (eg, 500 - Internal Server Error), we have WCF configured to put the message on a "retry" queue. 对于所有其他错误(例如500-内部服务器错误),我们将WCF配置为将消息放入“重试”队列。 Messages on the retry queue get retried after a certain amount of time. 经过一定时间后,重试队列上的消息将被重试。 The idea is that the server is temporarily down, so wait and try again. 想法是服务器暂时关闭,因此请重试。

The way WCF is set up, if we throw a FaultException in the service contract, it will automatically put the message on the retry queue. WCF的设置方式,如果我们在服务协定中抛出FaultException ,它将自动将消息放入重试队列。

When a message causes a 400 range error, we are just swallowing the error (we just log it). 当消息导致400范围错误时,我们只是吞下了该错误(我们只是记录了该错误)。 This prevents the retry mechanism from firing; 这样可以防止重试机制触发。 however, it would be better to move the message to a dead-letter queue. 但是,最好将消息移到死信队列中。 This way we can react to the error by sending an email to the user and/or a system administrator. 这样,我们可以通过向用户和/或系统管理员发送电子邮件来对错误做出反应。

Is there a way to immediately move these bad messages to a dead-letter queue? 有没有一种方法可以立即将这些不良消息移动到死信队列中?

First, I kept referring to the dead-letter queue. 首先,我一直提到死信队列。 At the time when I posted this question, I was unaware that WCF/MSMQ automatically creates what's known as a poison sub-queue. 当我发布此问题时,我还没有意识到WCF / MSMQ会自动创建所谓的有毒子队列。 Any message that can't be delivered in the configured number of times is put in the poison sub-queue. 任何无法在配置的次数内传递的消息都将放入毒物子队列中。

In my situation, I knew that some messages would never succeed, so I wanted to move the message out of the queue immediately. 在我的情况下,我知道某些消息永远不会成功,因此我想立即将消息移出队列。

The solution was to create a second queue that I called "poison" (not to be confused with the poison sub-queue). 解决方案是创建第二个队列,我称之为“毒药”(不要与毒药子队列相混淆)。 My catch block would create an instance of a WCF client and forward the message to this poison queue. 我的catch块将创建WCF客户端的实例,并将消息转发到该中毒队列。 I could reuse the same client to post to both the original queue and the poison queue; 我可以重用同一个客户端,以同时发布到原始队列和中毒队列; I just had to create a separate client end-point in the configuration file for each. 我只需要在每个配置文件中创建一个单独的客户端端点。

I had two separate ServiceHost instances running that read the queues. 我有两个运行的独立ServiceHost实例正在读取队列。 The ServiceHost for the original queue did the HTTP request and forwarded messages to the poison queue when unrecoverable errors occurred. 发生不可恢复的错误时,原始队列的ServiceHost执行HTTP请求,并将消息转发到中毒队列。 The second ServiceHost would simply send out an email to record that a message was lost. 第二个ServiceHost只需发送一封电子邮件以记录一条消息丢失。

There was also the issue of temporary errors that exceeded the maximum number of tries. 还有临时错误超出最大尝试次数的问题。 WCF/MSMQ automatically creates a sub-queue called <myqueuename>;poison . WCF / MSMQ自动创建一个名为<myqueuename>;poison的子队列。 You cannot directly write to a sub-queue via WCF, but you can read from it using a ServiceHost . 您不能通过WCF直接写入子队列,但可以使用ServiceHost从中读取。 Whenever messages end up in the poison sub-queue, I simply forward the message to the poison queue, with the exact same client I use in the original handler's catch block. 每当消息在有毒子队列中结束时,我都将消息转发到有毒剂队列,并使用与原始处理程序的catch块中使用的客户端完全相同的客户端。

I wanted the ability to include a stack trace in the error emails. 我希望能够在错误电子邮件中包含堆栈跟踪。 Since I was reusing the same client and service contract for all of the handlers, I couldn't just pass along the stack trace as a string (unless I added it to all of my data contracts). 由于我为所有处理程序重用了相同的客户端和服务协定,因此我不能只是将堆栈跟踪作为字符串传递(除非我将其添加到所有数据协定中)。 Instead, I had the poison handler try to execute the code one more time, which would fail again and spit out the stack trace. 取而代之的是,我让中毒处理程序尝试再次执行代码,这将再次失败并吐出堆栈跟踪。

This is what my message queues ended up looking like: 这就是我的消息队列的最终样子:

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

This approach is pretty convoluted. 这种方法非常复杂。 It was strange calling A WCF client from within a WCF service handler. 从WCF服务处理程序中调用WCF客户端很奇怪。 It also meant setting up one more queue on the server and a ton of additional configuration sections for specifying which queue a client should forward messages to. 这还意味着在服务器上再设置一个队列,并设置大量其他配置节来指定客户端应将消息转发到哪个队列。

hopefully I have understood your question and if it is what i think you are saying then yes there is but you obviously need to program it to do this. 希望我已经理解了您的问题,如果这是我认为您在说的话,那么是的,但是显然您需要对此进行编程。 But you DO need a retry amount set so the MSMQ can retry until it gives up. 但是您确实需要设置重试数量,以便MSMQ可以重试直到放弃。 Or you can create your own custom queue for dead letters/messages 或者,您可以为死信/消息创建自己的自定义队列

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://msdn.microsoft.com/en-us/library/ms789035(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/ms752268(v=vs.110)的.aspx

take a look here also: 在这里也看看:

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

How do I handle message failure in MSMQ bindings for WCF 如何处理WCF的MSMQ绑定中的消息失败

I hope these links help. 希望这些链接对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM