简体   繁体   English

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

[英]How to ensure JMS message redelivery when client crashes

I need to ensure redelivery of JMS messages when the consumer fails, but the strategies accepted on similar questions here might not apply to my case.我需要确保在消费者失败时重新传递 JMS 消息,但此处对类似问题所接受的策略可能不适用于我的情况。

Consider a JMS client - spring + activeMq - receiving messages, which cannot be lost or duplicated.考虑一个 JMS 客户端 - spring + activeMq - 接收不能丢失或复制的消息。 Because the processing of the messages is expensive, the client batch them.因为消息的处理成本很高,所以客户端将它们批处理。 The scenario plays as below:剧情如下:

  • T1 - Client receives messages A, B, C and D T1 - 客户端接收消息 A、B、C 和 D
  • T2 - A thread wakes up on the client and decides to handle messages A, B and C T2 - 一个线程在客户端唤醒并决定处理消息 A、B 和 C
  • T3 - Client receives messages E and F T3 - 客户端接收消息 E 和 F
  • T4 - The thread returns having processed A, B and C. It can then pick up the next batch if another thread has not done so already. T4 - 线程在处理完 A、B 和 C 后返回。如果另一个线程尚未这样做,则它可以拾取下一批。

The way the producer is set up now - DefaultJmsListenerContainerFactory and Session.AUTO_ACKNOWLEDGE - messages are removed as soon as they are delivered, whether they have been picked up by a thread or not.现在设置生产者的方式 - DefaultJmsListenerContainerFactorySession.AUTO_ACKNOWLEDGE - 消息在传递后立即被删除,无论它们是否已被线程接收。 If the client goes down just before T4 , messages A to F are lost.如果客户端在 T4 之前宕机,消息 A 到 F 将丢失。

I was planning to use Session.CLIENT_ACKNOWLEDGE on the producer and get each thread to call msg.acknowledge() after T4, but according to the documentation , this will also acknowledge E and F, which will be lost if the client fails after T4.我打算在生产者上使用Session.CLIENT_ACKNOWLEDGE并让每个线程在 T4 之后调用msg.acknowledge() ,但根据 文档,这也会确认 E 和 F,如果客户端在 T4 之后失败,这将丢失。

I am not convinced a transacted session will help here either, as it would cover messages A to F, while a thread completion only guaranties a subset of this has been processed.我不相信事务处理的会话在这里也有帮助,因为它会覆盖消息 A 到 F,而线程完成仅保证其中的一个子集已被处理。

My objective is to have a guarantee that in case of a failure of the client, eg the VM goes down, all the messages in flight that have not been successfully handled by a thread remains in the topic/queue.我的目标是保证在客户端出现故障的情况下,例如 VM 出现故障,线程未成功处理的所有正在传输的消息都保留在主题/队列中。 They can then be picked up by the client when it comes back up.然后,当它恢复时,客户可以拿起它们。

Any idea on how I can achieve this ?关于如何实现这一目标的任何想法?

S

The first thing i want to mention is that you should not use CLIENT_ACKNOWLEDGE cause you will make even worse and increase lose rate.我想提的第一件事是你不应该使用 CLIENT_ACKNOWLEDGE 因为你会变得更糟并增加丢失率。 Client acknowledge as u've said also will acknowledge all the messages in the related local jms session otherwise all your fetched messages from one batch.正如您所说,客户端确认也将确认相关本地 jms 会话中的所有消息,否则您从一批中获取的所有消息。

messages are removed as soon as they are delivered, whether they have been picked up by a thread or not消息在传递后立即被删除,无论它们是否已被线程接收

Usually acknowledge is send back when onMessage method invocation has finished.当 onMessage 方法调用完成时,通常会发回确认。 What thread did u mean?你说的是什么线程? If your processing is done in the same thread then it seems that it will send ack only after it's succeeded with invokation.如果您的处理是在同一个线程中完成的,那么它似乎只有在调用成功后才会发送 ack。

How did you achieve batch consuming?你是如何实现批量消费的? If u meant active mq consumer ( http://activemq.apache.org/performance-tuning.html ) and you are using provided by Spring (WS or Integration) and AMQ code base then you should put your efforts only on proper configuration and not to make some complex custom implementation to achieve 99.999999% success rate.如果你的意思是活跃的 mq 消费者( http://activemq.apache.org/performance-tuning.html )并且你使用的是 Spring(WS 或集成)和 AMQ 代码库提供的,那么你应该只把精力放在正确的配置和不要做一些复杂的自定义实现来达到99.999999%的成功率。 Every jms broker lose messages or have duplicates and youll never get 0 lose rate.每个 jms 代理都会丢失消息或有重复项,您永远不会得到 0 丢失率。 And for most enterprise systems it is a normal case when for exampe 1 out of million messages got lost or duplicated.对于大多数企业系统而言,例如百万分之一的消息丢失或重复是正常情况。

To get somehow reliable delivery you should use persistent delivery mode and jms transactions anyway.为了获得某种可靠的交付,您无论如何都应该使用持久交付模式和 jms 事务。 For me duplicated messages are better than completely lost (actually all system architecture should be build idempotent for treating such things).对我来说,重复的消息总比完全丢失要好(实际上所有系统架构都应该为处理这些事情而构建幂等)。 And as you've said and as also mentioned is AMQ docs batch is a tradeoff between reliability and performance.正如您所说,并且还提到 AMQ 文档批处理是可靠性和性能之间的权衡。 And fundamentally there is no chance to achieve both properties simultaneously.基本上没有机会同时实现这两个属性。 At least with AMQ and jms.至少有 AMQ 和 jms。 So it is after you to decide what is more important for you reliability or performace.因此,由您来决定哪个对您的可靠性或性能更重要。 The most optimal choice for you will be to define that tradeoff and decide what batch amount of duplicated messages is acceptable in case of lost or duplicate messages最适合您的选择是定义该权衡并决定在丢失或重复消息的情况下可接受的重复消息批量

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM