使用ThreadPool和JMS时处理JVM崩溃

时间:2013-02-04 18:31:45

标签: java transactions jms jvm-crash

我有一个独立的Java进程,它从JMS持久主题中读取消息并将它们提交给线程池进行处理。我出于明显的并发原因这样做,但是维护这些消息的处理顺序,我仍然将它们提交给单个线程池。现在这里是我对JVM崩溃的担忧..

- 非交易的 我不是在阅读和处理Transactional上下文中的每条消息,我避免这会减慢我的进程。所以,我在线程池的阻塞队列中累积消息。但是如果JVM崩溃,而等待处理的线程池中有10条消息,我将丢失该数据。

- 事务
我相信如果我在事务中阅读并处理每条消息,如果出现问题,该消息将在备份时重新传递给该进程。

对于在低延迟系统中工作的许多人来说,这是一个常见问题,想知道有经验的人如何处理这个问题?感谢。

1 个答案:

答案 0 :(得分:1)

彼得的AFAIK是正确的。解决此问题的一种方法是,如果模式适用于您,则使用某种划分来创建不同的队列以将消息分组到其中。也就是说,此要求经常被分解为“一个帐户的所有邮件必须按顺序处理”。因此,如果你有类似的东西,你可以创建:

  • 一个主题,并且有多个订阅者,每个订阅者都使用独占选择器(或子主题模式)
  • 多个主题,每个主题都有一个订阅者。

然后您的出版商必须确定:

  • 已发布邮件的标题,以便更正订阅者对订阅者,或
  • 要发布的正确子主题,或
  • 要在
  • 上发布的正确主题

执行此操作的易于维护的模式是使用您的某个业务字段(例如,帐号)并在其上计算 mod(x),其中 x 是您希望共享工作负载的订户数量。希望您的业务密钥是数字的,并且会给您一个不错的分配,但是您总是可以使用其他一些确定性算法通过反转键和/或散列它们的非数字值来生成此数字。

顺便说一句,你的大纲对它有更多的点对点/ JMS队列感觉,而不是Pub-Sub / JMS主题。您确定要使用主题吗?

如果绝对不能丢失数据,那么您应该使用事务性消息。如果使用事务性消息,则无法委派给线程池。 JMS消息的事务上下文(即会话)绑定到接收消息的线程,因此,除非您启用一些“有趣的业务”将此上下文转移到另一个线程.....

我甚至不确定如何完成那句话。

====更新====

现在我考虑一下,如果您可以从并行处理消息中受益,您可以在一个事务中检索批量消息,并将它们全部委托给ExecutorService.invokeAll调用,等待完成和在交易全部完成时提交交易。如果invokeAll超时,或者其中一个任务抛出异常,那么您将不得不回滚事务或采取某种补偿操作。