2017-01-06 38 views
0

有关请求/响应模式的MassTransit 3+中处理异常的最佳做法是什么? docs here提到,如果消息中存在响应地址,则故障消息将被发送到该地址,但是一个消费者如何接收该地址的消息? Bus.Request的ResponseAddress似乎是自动生成的MassTransit地址,我无法控制,所以我不知道如何访问主消费者中引发的异常。我错过了什么?这里是我的代码以注册消费者和其使用故障消费者团结容器:MassTransit故障消费者未针对请求/响应调用

cfg.ReceiveEndpoint(host, "request_response_queue", e => 
{ 
    e.Consumer<IConsumer<IRequestResponse>>(container); 
    e.Consumer(() => container.Resolve<IMessageFaultConsumer<IRequestResponse>>() as IConsumer<Fault<IRequestResponse>>); 
}); 

而且这里是我在一个全球性的消息故障消费者尝试:当我使用Bus.Publish

public interface IMessageFaultConsumer<TMessage> 
{ 
} 

public class MessageFaultConsumer<TMessage> : IConsumer<Fault<TMessage>>, IMessageFaultConsumer<TMessage> 
{ 
    public Task Consume(ConsumeContext<Fault<TMessage>> context) 
    { 
     Console.WriteLine("MessageFaultConsumer"); 
     return Task.FromResult(0); 
    } 
} 

这种方法确实可行而不是Bus.Request。我还着眼于创建一个IConsumeObserver并将我的全局异常日志记录代码放入ConsumeFault方法中,但是在重新尝试放弃之前,每次异常都会调用它的缺点。处理请求/响应异常的正确方法是什么?

回答

1

首先,MassTransit中的请求/响应支持旨在与.Request()方法或请求客户端(MessageRequestClientPublishRequestClient)一起使用。使用这些方法,如果请求消息的使用者抛出异常,则将该异常打包到发送到ResponseAddressFault<T>。由于.Request()方法和请求客户端都是异步的,因此使用await将抛出一个异常,并且包含故障中的异常数据。这就是它的设计,等待请求,它会完成,超时或错误(在等待时抛出异常)。

如果您为了记录目的而试图放入一些全局“异常处理程序”代码,那么您确实应该在服务边界处记录这些代码,而观察者是处理它的最佳方式。这样,您可以实施ConsumeFault方法,并登录到事件接收器。但是,这在消费者渠道中是同步的,因此要认识到可能引入的延迟。

另一种选择当然是消耗Fault<T>,但正如您所提到的,当请求客户端与头中的响应地址一起使用时,它不会被发布。在这种情况下,或许您的请求者应该发布一个事件,指出操作X发生故障,并且您可以在业务上下文级别与服务级别上记录该事件。

这里有很多选择,它只是选择一个最适合您的用例。