我正在寻找一个很好的解决方案来记录失败的消息,在超过重试限制之后,没有处理错误队列。到目前为止我发现了什么:
作为一个解决方案,我可以在 PreDispatch 中将 IConsumeContext 放入某种缓存中,然后将其从 IsRetryLimitExceeded中的缓存中取出超出重试限制时。
按以下顺序调用方法: IsRetryLimitExceeded - > PreDispatch - >执行postDispatch
所以我找不到从缓存中删除成功处理的邮件的好地方。
当然我可以使用大小有限的缓存,但整个解决方案似乎很奇怪。
对此问题的任何想法将不胜感激。
答案 0 :(得分:4)
我已经开始使用这个解决方案了:
class MessageInterceptor: IInboundMessageInterceptor
{
public void PreDispatch(IConsumeContext context)
{
MessageTracker.Register(context);
}
public void PostDispatch(IConsumeContext context)
{}
}
class MessageTracker: InMemoryInboundMessageTracker
{
readonly Logger logger;
static readonly ConcurrentDictionary<string, IConsumeContext> DispatchingCache = new ConcurrentDictionary<string, IConsumeContext>();
public MessageTracker(int retryLimit, Logger logger)
: base(retryLimit)
{
this.logger = logger;
}
public static void Register(IConsumeContext context)
{
DispatchingCache.GetOrAdd(context.MessageId, context);
}
public override void MessageWasReceivedSuccessfully(string id)
{
base.MessageWasReceivedSuccessfully(id);
IConsumeContext value;
DispatchingCache.TryRemove(id, out value);
}
public override bool IsRetryLimitExceeded(string id, out Exception retryException, out IEnumerable<Action> faultActions)
{
var result = base.IsRetryLimitExceeded(id, out retryException, out faultActions);
IConsumeContext failed;
if (!result || !DispatchingCache.TryRemove(id, out failed))
return result;
// --> log failed IConsumeContext with exception
return true;
}
}
并在
中插入这些类 serviceBus = ServiceBusFactory.New(config =>
{
...
config.AddBusConfigurator(new PostCreateBusBuilderConfigurator(sb =>
{
var interceptorConfig = new InboundMessageInterceptorConfigurator(sb.InboundPipeline);
interceptorConfig.Create(new MessageInterceptor());
}));
config.SetDefaultInboundMessageTrackerFactory(retryLimit => new MessageTracker(retryLimit, LogManager.GetCurrentClassLogger()));
});
答案 1 :(得分:2)
您可以在总线上实现和配置自己的消息重试跟踪,以便通过您的实现传递失败的消息。您可以委派默认的重试跟踪器,只是拦截事件以便您可以对它们采取行动,或者您可以根据需要实施自己的重试跟踪。
MessageTrackerFactory是用于配置的委托,我认为接口就在附近。