有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在客户端崩溃时确保JMS消息的重新传递

我需要确保在消费者失败时重新交付JMS消息,但在类似问题上接受的策略可能不适用于我的情况

考虑一个JMS客户端- Spring + ActudiMQ -接收消息,这些消息不能丢失或复制。由于处理消息的成本很高,客户端会对其进行批处理。场景如下所示:

  • T1-客户端接收消息A、B、C和D
  • T2-一个线程在客户端上醒来,并决定处理消息A、B和C
  • T3-客户端接收消息E和F
  • T4-线程返回时已处理了A、B和C。如果另一个线程尚未处理完,则它可以选择下一批

制作人现在的设置方式--DefaultJmsListenerContainerFactory会话。AUTO_ACKNOWLEDGE(自动确认)——消息一经发送,无论是否被线程接收,都会立即被删除。如果客户机在T4之前停机,消息A到F将丢失

我计划使用会话。客户_确认制作人,并让每个线程调用消息。acknowledge()在T4之后,但根据documentation,这也将确认E和F,如果客户端在T4之后失败,这将丢失

我不相信事务处理会话在这里也会有帮助,因为它会覆盖消息a到F,而线程完成只能保证其中的一个子集已被处理

我的目标是确保在客户端出现故障(例如VM宕机)的情况下,未被线程成功处理的所有正在传输的消息仍保留在主题/队列中。然后,当它返回时,客户可以将其提取

你知道我该怎么做吗

S


共 (1) 个答案

  1. # 1 楼答案

    我想说的第一件事是,你不应该使用CLIENT_ACKNOWLEDGE,因为你会变得更糟,增加损失率。正如你所说的,客户端确认还会确认相关本地jms会话中的所有消息,否则会确认从一个批处理中获取的所有消息

    messages are removed as soon as they are delivered, whether they have been picked up by a thread or not

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

    你是如何实现批量消费的?如果你指的是活动mq使用者(http://activemq.apache.org/performance-tuning.html),而你使用的是Spring(WS或Integration)和AMQ代码库,那么你应该只在适当的配置上下功夫,而不是为了实现99.99999%的成功率而进行一些复杂的定制实现。每个jms代理都会丢失消息或有重复的消息,您永远不会得到0的丢失率。对于大多数企业系统来说,100万条消息中有1条丢失或重复是正常情况

    为了以某种方式获得可靠的交付,无论如何都应该使用持久交付模式和jms事务。对我来说,重复的消息总比完全丢失的消息好(实际上,所有的系统架构都应该是用来处理这些事情的幂等元)。正如你所说,AMQ文档批处理是可靠性和性能之间的折衷。从根本上说,不可能同时实现这两种特性。至少使用AMQ和jms。因此,你需要决定什么对你的可靠性或表现更重要。对于您来说,最理想的选择是定义折衷方案,并决定在丢失或重复消息的情况下,可以接受多少批重复消息