Nservicebus 针对特定类型的异常的Nsb:跳过SLR+;忽略错误队列的能力

Nservicebus 针对特定类型的异常的Nsb:跳过SLR+;忽略错误队列的能力,nservicebus,Nservicebus,我希望有一个中心位置来实现特定类型异常的异常处理逻辑 如果发生特定的异常类型,我希望能够根据内部配置运行以下其中一项: 立即将消息发送到错误队列,无需进一步的二级重试 隐藏消息,不将其发送到处理队列或错误队列 我发现这个主题涉及第一种情况,但不涉及第二种情况,因为如果我们返回TimeSpan.MinValue,消息将被放入错误队列: 那么我如何实施第二个案例呢?在NServiceBus第6版之前,最好在一个地方、一个类中实现这两个功能,您可以使用IManageMessageFailures

我希望有一个中心位置来实现特定类型异常的异常处理逻辑

如果发生特定的异常类型,我希望能够根据内部配置运行以下其中一项:

  • 立即将消息发送到错误队列,无需进一步的二级重试
  • 隐藏消息,不将其发送到处理队列或错误队列
我发现这个主题涉及第一种情况,但不涉及第二种情况,因为如果我们返回
TimeSpan.MinValue
,消息将被放入错误队列:


那么我如何实施第二个案例呢?在NServiceBus第6版之前,最好在一个地方、一个类中实现这两个功能,您可以使用
IManageMessageFailures
来管理消息故障。您可以处理序列化异常的情况,或者在尝试第一级重试后无法正常处理消息的情况下(与您手头的问题更相关)

下面介绍如何实现一个自定义的
FaultManager
,它可以忽略某些类型的异常,或者将带有其他错误的失败消息发送回错误队列。请注意,第一级退出仍然会发生,这将取代第二级重试

public class IssueOrder : ICommand
{
    public bool NotFound { get; set; }
    public bool HasFaulted { get; set; }
}

public class OrderHandler : IHandleMessages<IssueOrder>
{
    public void Handle(IssueOrder message)
    {
        if(message.NotFound)
            throw new OrderNotFoundException();

        if(message.HasFaulted)
            throw new ApplicationException();
    }
}

public class OrderNotFoundException : Exception
{
}

public class CustomFaultManager : IManageMessageFailures
{
    private ISendMessages sender;
    private MessageForwardingInCaseOfFaultConfig config;
    private BusNotifications notifications;
    private static ILog Logger = LogManager.GetLogger<CustomFaultManager>();

    public CustomFaultManager(ISendMessages sender, IProvideConfiguration<MessageForwardingInCaseOfFaultConfig> config)
    {
        this.sender = sender;
        this.config = config.GetConfiguration();
    }

    public void SerializationFailedForMessage(TransportMessage message, Exception e)
    {
    }

    public void ProcessingAlwaysFailsForMessage(TransportMessage message, Exception e)
    {
        if (e is OrderNotFoundException)
        {
            //Ignore the exception;
            Logger.WarnFormat("OrderNotFoundException was thrown. Ignoring the message Id {0}.", message.Id);
        }
        else
        {
            //Check if you have performed enough retries, ultimately send to error queue
            SendToErrorQueue(message, e);
        }
    }

    private void SendToErrorQueue(TransportMessage message, Exception ex)
    {
        message.TimeToBeReceived = TimeSpan.MaxValue;
        sender.Send(message, new SendOptions(config.ErrorQueue));
        Logger.WarnFormat("Message {0} will was moved to the error queue.", message.Id);
    }

    public void Init(Address address)
    {
    }
}
公共类发布顺序:ICommand
{
公共布尔未找到{get;set;}
公共布尔值已出错{get;set;}
}
公共类OrderHandler:IHandleMessages
{
公共无效句柄(IssueOrder消息)
{
if(message.NotFound)
抛出新的OrderNotFoundException();
if(message.HasFaulted)
抛出新的ApplicationException();
}
}
公共类OrderNotFoundException:异常
{
}
公共类CustomFaultManager:IManageMessageFailures
{
私密信息发送者;
private MessageForwardingCaseofFaultConfig配置;
私人巴士通知;
私有静态ILog Logger=LogManager.GetLogger();
public CustomFaultManager(ISendMessages发件人,IProvidConfiguration配置)
{
this.sender=发送方;
this.config=config.GetConfiguration();
}
public void serializationFailedFormMessage(TransportMessage消息,异常e)
{
}
public void ProcessingAlwaysFailsForMessage(传输消息消息,异常e)
{
如果(e是OrderNotFoundException)
{
//忽略例外;
WarnFormat(“引发OrderNotFoundException。忽略消息Id{0}.”,message.Id);
}
其他的
{
//检查您是否执行了足够的重试,并最终发送到错误队列
发送到错误队列(消息,e);
}
}
私有void SendToErrorQueue(TransportMessage消息,异常ex)
{
message.TimeToBeReceived=TimeSpan.MaxValue;
sender.Send(message,newsendpoptions(config.ErrorQueue));
WarnFormat(“消息{0}将被移动到错误队列。”,Message.Id);
}
公共void Init(地址)
{
}
}
要注册自定义FaultManager,请执行以下操作:

var config = new BusConfiguration();
//Other configuration code
config.RegisterComponents(c =>
        {
            c.ConfigureComponent<CustomFaultManager>(DependencyLifecycle.InstancePerCall);
        });
var config=new-BusConfiguration();
//其他配置代码
配置注册表组件(c=>
{
c、 配置组件(DependencyLifecycle.InstancePerCall);
});

但是,在NServiceBus的第6版中,不推荐使用
IManageMessageFailures
接口。版本6中的新版本允许更好的定制,尽管没有直接忽略/禁用异常的方法。为此,您需要在NServiceBUs中使用自定义行为,并在已知步骤之一之间的步骤中运行它(例如,在将消息移动到错误队列之前)。

您能否再详细说明一下?我们使用Nsb 5,但我不知道如何在所有情况下实现1)消息隐藏2)正常SLR 3)没有带IManageMessageFailures的SLR。它说“启用此扩展时,将不会调用第二级重试”。其次,我看不到什么处理程序可以为“在消息移动到错误队列之前”的事件提供服务,它只有
SerializationFailedForMessage
ProcessingAlwaysFailsForMessage
我正在收集一个更好的示例,展示如何实现自定义故障管理器,请容忍我。@YMC请查看代码是否适合您。我还将更新NSB docs网站上的v5示例。@HadiEskandari,我正在NServiceBus 5端点中使用Autofac,当我尝试添加config.RegisterComponents代码时,出现以下异常:无法解析参数“NServiceBus.config.ConfigurationSource.iproviderConfiguration
1[NServiceBus.config.MessageForwardingCaseofFaultConfig]构造函数Void.ctor(NServiceBus.Transports.ISendMessages,NServiceBus.config.ConfigurationSource.IProvideConfiguration
1[NServiceBus.config.messageforwardingcaseoftfaultconfig])的配置。app.config文件有,因此它是在配置中设置的,但由于某些原因,显然无法由Autofac解析。