使用 JMS 队列的潜在陷阱?

2022-09-04 22:17:02

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

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

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

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

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

对于策略 1,我很清楚如何满足这些要求,但它可能不如策略 2 健壮和可扩展,而且开发起来更复杂,因为我需要编写自己的多线程代码来处理各种独立队列。我想知道为此目的使用JMS队列可能有什么潜在的陷阱,因为我以前从未使用过它们。

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

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


答案 1

Kaleb的回答非常雄辩地谈到了JMS的好处,但是既然你问的是陷阱,这就是我能想到的。

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

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


答案 2

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

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

然后,您的 Java 应用程序将完全在不同的服务器上运行,并将连接到代理并尽可能快地从队列中提取消息。如果应用程序服务器崩溃或因任何其他原因停止拾取消息,则代理将保留该队列中的所有消息,直到应用程序服务器再次开始拾取它们。


推荐