Nsb 对于某些类型的异常:跳过 SLR + 忽略错误队列的能力
Nsb for certain type of exceptions: skip SLR + ability to ignore error queue
我希望有一个中心位置来为特定类型的异常实施异常处理逻辑。
如果出现特定的异常类型,我希望能够 运行 根据内部配置执行以下操作之一:
- 立即将消息发送到错误队列,无需进一步的二级重试;
- 隐藏消息,不发送到处理队列或错误队列;
我发现这个主题涵盖了第一种情况,但不包括第二种情况,因为如果我们 return TimeSpan.MinValue
,消息将被放入错误队列:
NServiceBus error handling
那么我该如何实现第二种情况呢?最好都在一个地方实施,一个 class
在 NServiceBus 版本 6 之前,您可以使用 IManageMessageFailures
来管理消息失败。您可以处理序列化异常的情况,或者 - 与您手头的问题更相关 - 在尝试一级重试后无法正常处理消息时。
以下是实现自定义 FaultManager
的方法,该自定义 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)
{
}
}
并注册自定义 FaultManager:
var config = new BusConfiguration();
//Other configuration code
config.RegisterComponents(c =>
{
c.ConfigureComponent<CustomFaultManager>(DependencyLifecycle.InstancePerCall);
});
然而,在 NServiceBus 的版本 6 中,IManageMessageFailures
接口已被弃用。新的 Recoverability api in version 6 allows for better customization, althrough there's no direct way of ignoring/muting an exception. For that purpose you need a custom behavior in the NServiceBUs pipeline 和 运行 它位于已知步骤之一之间的步骤中(例如,在将消息移至错误队列之前)。
我希望有一个中心位置来为特定类型的异常实施异常处理逻辑。
如果出现特定的异常类型,我希望能够 运行 根据内部配置执行以下操作之一:
- 立即将消息发送到错误队列,无需进一步的二级重试;
- 隐藏消息,不发送到处理队列或错误队列;
我发现这个主题涵盖了第一种情况,但不包括第二种情况,因为如果我们 return TimeSpan.MinValue
,消息将被放入错误队列:
NServiceBus error handling
那么我该如何实现第二种情况呢?最好都在一个地方实施,一个 class
在 NServiceBus 版本 6 之前,您可以使用 IManageMessageFailures
来管理消息失败。您可以处理序列化异常的情况,或者 - 与您手头的问题更相关 - 在尝试一级重试后无法正常处理消息时。
以下是实现自定义 FaultManager
的方法,该自定义 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)
{
}
}
并注册自定义 FaultManager:
var config = new BusConfiguration();
//Other configuration code
config.RegisterComponents(c =>
{
c.ConfigureComponent<CustomFaultManager>(DependencyLifecycle.InstancePerCall);
});
然而,在 NServiceBus 的版本 6 中,IManageMessageFailures
接口已被弃用。新的 Recoverability api in version 6 allows for better customization, althrough there's no direct way of ignoring/muting an exception. For that purpose you need a custom behavior in the NServiceBUs pipeline 和 运行 它位于已知步骤之一之间的步骤中(例如,在将消息移至错误队列之前)。