如何在masstransit中记录失败的消息?

时间:2013-11-21 10:43:11

标签: .net masstransit

我正在寻找一个很好的解决方案来记录失败的消息,在超过重试限制之后,没有处理错误队列。到目前为止我发现了什么:

  • 我可以继承 InMemoryInboundMessageTracker 并覆盖 IsRetryLimitExceeded ,但此时除了id之外没有关于消息本身的信息。
  • 我可以在 Pre / PostDispatch 中实现 IInboundMessageInterceptor 并获取 IConsumeContext ,但此时没有关于成功/失败的信息。

作为一个解决方案,我可以在 PreDispatch 中将 IConsumeContext 放入某种缓存中,然后将其从 IsRetryLimitExceeded中的缓存中取出超出重试限制时。

按以下顺序调用方法: IsRetryLimitExceeded - > PreDispatch - >执行postDispatch

所以我找不到从缓存中删除成功处理的邮件的好地方。

当然我可以使用大小有限的缓存,但整个解决方案似乎很奇怪。

对此问题的任何想法将不胜感激。

2 个答案:

答案 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是用于配置的委托,我认为接口就在附近。