如何在客户端崩溃时确保重新发送JMS消息

时间:2017-09-25 11:49:50

标签: java spring jms batch-processing spring-jms

我需要确保在消费者失败时重新发送JMS消息,但此处类似问题所接受的策略可能不适用于我的情况。

考虑一个JMS客户端 - spring + activeMq - 接收不会丢失或重复的消息。因为消息的处理很昂贵,所以客户端批量处理它们。场景如下:

  • T1 - 客户端收到消息A,B,C和D
  • T2 - 线程在客户端唤醒并决定处理消息A,B和C
  • T3 - 客户端收到消息E和F
  • T4 - 线程返回已处理过的A,B和C.如果另一个线程尚未这样做,它可以接收下一批。

现在设置制作人的方式 - DefaultJmsListenerContainerFactory Session.AUTO_ACKNOWLEDGE - 邮件一旦发送就会被删除,无论是否被线程与否。如果客户端在T4之前发生故障,则消息A至F将丢失。

我计划在制作人上使用 Session.CLIENT_ACKNOWLEDGE ,并让每个帖子在T4之后调用 msg.acknowledge(),但根据{{3}这也将确认E和F,如果客户端在T4之后失败,它将丢失。

我不相信交易会话会对此有所帮助,因为它会覆盖消息A到F,而线程完成只保证其中一部分已被处理。

我的目标是保证在客户失败的情况下,例如VM停止运行,线程中未成功处理的所有正在传递的消息仍保留在主题/队列中。然后客户可以在重新启动时接听它们。

有关如何实现这一目标的任何想法吗?

取值

1 个答案:

答案 0 :(得分:1)

我想提到的第一件事是你不应该使用CLIENT_ACKNOWLEDGE因为你会更糟糕并且增加失败率。客户确认,因为您已经说过也将确认相关本地jms会话中的所有消息,否则将从一个批次中获取所有已获取的消息。

  

邮件一旦发送就会被删除,无论是否有   是否已被线程接听

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

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

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

相关问题