2017-09-25 27 views
0

当消费者失败时,我需要确保重新传递JMS消息,但这里类似问题上接受的策略可能不适用于我的情况。如何在客户端崩溃时确保JMS消息重新传递

考虑一个JMS客户端 - spring + activeMq--接收不会丢失或重复的消息。由于消息的处理非常昂贵,客户端会批量处理它们。场景播放如下:

  • T1 - 客户端接收消息A,B,C和d
  • T2 - 线程在客户端上被唤醒并决定处理消息A,B和C
  • T3 - 客户端收到消息E和F
  • T4 - 线程返回已处理A,B和C的数据。如果另一个线程尚未完成,它可以接收下一批。

生产者建立现在的方式 - 消息,尽快为他们交付删除,是否已经由一个线程拿起与否 -和Session.AUTO_ACKNOWLEDGEDefaultJmsListenerContainerFactory。如果客户在T4之前停机,则消息A到F将丢失。

我正打算使用Session.CLIENT_ACKNOWLEDGE在生产者和获得每个线程T4之后调用msg.acknowledge(),但根据documentation,这也将确认E和F,这将是如果客户在T4之后失败,则丢失。

我不确定交易会话是否会对此有所帮助,因为它将涵盖消息A到F,而线程完成只保证已处理该消息的子集。

我的目标是保证在发生客户端故障时(例如,虚拟机停机,所有尚未被线程成功处理的消息都保留在主题/队列中。当客户回来时,他们可以被客户接收。

关于如何实现这一点的任何想法?

小号

回答

0

我想提的第一件事情是,你不应该使用CLIENT_ACKNOWLEDGE原因你会更差,提高输率。客户端确认,因为你所说的还会承认相关本地jms会话中的所有消息,否则将确认来自一个批次的所有提取的消息。

消息,尽快为他们交付拆除,它们是否 被一个线程拿起或不

通常承认是送回来时,onMessage方法调用已完成。你的意思是什么线索?如果您的处理是在同一个线程中完成的,那么它似乎只会在调用成功后才会发送确认。

你是如何实现批量消费的?如果你的意思是活跃的mq消费者(http://activemq.apache.org/performance-tuning.html),并且你正在使用Spring(WS或Integration)和AMQ代码库提供的功能,那么你应该只将自己的努力放在适当的配置上,而不是做一些复杂的自定义实现来达到99.999999%的成功率。每个jms经纪人都会丢失消息或者有重复的消息,并且你永远不会得到0的丢失率。而对于大多数企业系统来说,这是一个正常的情况,例如,万分之一的消息丢失或重复。

为了得到某种可靠的交付,你应该使用持久交付模式和jms交易。对我而言,重复的消息要比完全丢失更好(实际上,所有系统架构都应该被构建为处理这种事情的幂等)。正如你所说,AMQ文档批次也是可靠性与性能之间的折衷。从根本上说,没有机会同时实现两个属性。至少通过AMQ和jms。所以这是在你决定什么对你来说更重要的可靠性或表现。对于您来说,最理想的选择是定义这种权衡,并确定哪些批量的重复邮件在丢失或重复邮件的情况下是可以接受的。

+0

是的,auto_ack在onMessage()完成后完成。目前,此方法仅将消息添加到集合(以简化)并返回。当满足某些条件(时间,集合的大小...)时,线程决定是时候处理集合中的部分消息。这意味着在auto_ack中,msg ack和实际处理之间会有一段时间。也许我所追求的是不可行的,正如你所说的,我只需要配置集合的大小以至多保留我可以承受的最小丢失数量。 –

+0

在这种情况下,实际上您可以使用像mapdb或smth这样的持久数据结构。从发送邮件到某个内部渠道的那一刻起,实际上您有责任在此邮件的进一步访问后留心。试图通过经纪人完成这项工作将导致复杂的逻辑没有任何需要。但对我来说,即使mapdb看起来像一个开销,我怀疑你的情况是一个好的架构。从我的角度来看,最好的选择就是建议您可以丢失或获取一些较低信息量的重复项并设置合适的窗口大小 –