时间:2010-01-30 02:32:33

标签: java jms message-queue database

我被要求设计并实施一个系统,用于从大量设备接收大量自动传感器数据。此数据将定期生成,并作为xml在http帖子中发送到服务器。如果设备未从服务器收到特定确认,则设备将继续重新发送相同的数据。在通过事务将数据插入主数据库中的多个表之前,需要对此数据进行一些潜在的重负荷处理,此外,还需要将一些数据点入队以重定向到其他外部URL。

我打算使用Java应用程序服务器(倾向于GlassFish)和servlet来接收传入的数据。我想实现某种排队机制来临时存储数据,以便返回传感器的响应不依赖于所有中间处理。单独的独立队列也是数据重定向部分的要求。在做了一些研究之后,两个主要的选择似乎是:

1)在应用服务器上安装数据库,并使用各种队列的表。队列将由Java应用程序处理,可以在应用程序服务器中运行,也可以作为自己的服务独立运行。

2)使用数据库支持的JMS解决方案来实现排队。

我对JMS并不熟悉,但从我读过的内容来看,似乎是这种情况下更好的解决方案。主要要求是在处理之前没有传感器数据丢失或从队列中丢弃,并且它或多或少地按顺序处理。我们还希望在某些时候可以轻松停止某些队列的处理,但仍然会让它们累积数据并且这些消息永远不会自动过期。

对于策略1,我很明显如何满足这些要求,但它可能不那么健壮和可扩展,并且比策略2更复杂,因为我需要编写自己的多线程代码来处理各种需求独立队列。我想知道在为此目的使用JMS队列时可能存在的潜在缺陷是什么,因为我之前从未使用过它们。

数据完整性是一个大问题,所以我需要确保JMS能够保证在服务器重启,停电或者由于某种原因队列变得非常大的情况下不会丢失数据。例如,在一段时间内完成到主数据库的事务可能导致JVM耗尽内存,崩溃并丢失所有累积数据? (这将是噩梦般的场景)。

另外,我想知道是否有任何方法可以通过应用服务器管理工​​具暂停JMS队列处理或轻松查看队列中的内容(我会将一个对象排入队列,这将是消息xml加上其他一些数据,包括收到的时间戳等。)我在这里阅读了一些处理相关问题但希望得到一些直接反馈的帖子。基本上我想知道JMS不是一个合适的排队解决方案的实例(如果有的话),如果这是其中一个案例。非常感谢任何建议。

3 个答案:

答案 0 :(得分:7)

Kaleb的回答很有说服力地谈论了JMS的好处,但是既然你在询问陷阱,那么这就是我能想到的。

  • 并非所有JMS实现都是相同的。理论上,您可以使用适合您需要的任何实现,但除非您准备进行一些严重的负载测试和故障条件测试,否则您无法知道特定实现在您的特定用例下不会失败。
  • 大多数JMS使用事务数据存储区(如关系数据库)作为后端。这意味着,您不必直接写入您熟悉的任何数据存储区,而是必须依赖于JMS实现在您和存储的消息之间的额外层。
  • 虽然交换JMS实现以找到完全符合您需求的实现,但由于同类JMS API,故障处理的关键功能,JMS服务器监控以及上面存在的所有其他很酷的东西,看起来似乎是一件简单的事情。如果你确实改变了你的实现,那么除了消息之外的处理将会很麻烦。

那就是说,我认为你自己写DB而不是和JMS一起去疯狂。在第一点,ActiveMQ是一个在许多企业环境中使用的古老的JMS服务器。关于第二点,事实是你最终会自己编写额外的层以实现消息传递,而你的代码将无法获得成千上万的眼睛(或者是一组付费开发人员,他们唯一的工作就是响应客户并确保JMS实施是可靠的。在第三点上,您的后端数据存储区也是如此。使用JMS,从长远来看,你可以省去麻烦。

答案 1 :(得分:3)

如果您想要使用JMS路由,那么独立的JMS兼容消息代理(与您的应用服务器分开)将是一个不错的选择。消息代理的范围从免费的开源(如http://activemq.apache.org/的ActiveMQ或https://mq.dev.java.net/的OpenMQ)到大型商业解决方案(IBM http://www-01.ibm.com/software/integration/wmq/的WebSphere MQ是最大的解决方案之一)。

消息代理提供有保证的交付(提供服务器启动和监听),您可以做很多事情来确保系统是故障安全的,包括集成的备份代理服务器和即时电源备份。如果您的应用服务器没有接收消息,代理队列最终会耗尽空间,但您可以分配巨大的队列深度(100的GB)并让服务器发送警报,如果消息未得到处理且队列到达一定比例。

然后,您的Java应用程序将完全在另一台服务器上运行,并将连接到代理并尽快将消息从队列中拉出。如果应用服务器由于任何其他原因而崩溃或停止接收消息,则代理会将所有消息保留在该队列中,直到应用服务器再次开始接收它们为止。

答案 2 :(得分:0)

您将希望在您的实现中实现一个有害消息队列 - 这是在一些重试次数到来后无法处理消息的地方。

您可能需要编写一些代码,这些代码可以检查该队列中的消息,并在修复导致它们失败的任何内容后将它们重新发送到适当的目标。

如果消息处理序列很重要,则在毒性队列中结束的消息可能意味着所有处理都将暂停,直到该消息得到纠正。

就容错而言,您可以让消费服务的多个实例订阅同一个队列或主题,从而提供即使一个或多个实例发生故障也能继续处理的能力。

最后,有一个监视程序进程可以对邮件队列中的各种使用者进行ping操作,如果没有响应,请让它发送一条消息,导致新实例启动。通过这种方式,您的消息处理环境可以在某种程度上自我调节。