【问题标题】:Scalability of Java EE Application. How would you approach it?Java EE 应用程序的可伸缩性。你会如何处理它?
【发布时间】:2010-10-12 23:05:10
【问题描述】:

我一直致力于为金融行业提供解决方案。该应用程序的主要功能是能够加载大量输入文件、消化它们、更新持久存储中的状态并根据请求从持久存储中生成提取。很简单。

输入文件是行业标准格式的 XML 大型(超过数百兆字节)消息,其中包含许多重复条目。持久存储是关系数据库。该引擎已实现为可部署在 J2EE 应用服务器上的基于 POJO(以 Spring 框架为骨干)的 Java 应用程序。

问题在于解决方案的可扩展性和性能。如果应用程序按顺序处理来自 XML 的条目,则解决方案的可伸缩性相当差。没有办法让应用程序的多个实例参与单个文件的处理。这就是我为输入 XML 文件中的条目引入并行处理的原因。基本上,这个想法是为池中的工人分派处理单个条目。我决定使用 JMS 进行调度。加载文件的组件读取流并简单地提取单个条目并提供给调度队列。队列的另一端有许多并发消费者。每个人从队列中挑选一条消息并处理该条目,它可以立即用于处理其他条目。这与 Web 容器中的 servlet 非常相似。我发现这种方法特别强大的是,只要队列是共享的,工作人员就可以驻留在部署在远程服务器上的应用程序的不同实例中。不幸的是,所有工作人员都连接到维护持久性存储的同一个数据库,如果数据库服务器的功能不足以处理来自并发工作人员的负载,这可能是一个瓶颈。

您对此架构有何看法?你有类似的应用程序设计吗?你当时的设计选择是什么?

【问题讨论】:

    标签: java jakarta-ee concurrency scalability jms


    【解决方案1】:

    您还可以查看 Hadoop,这是一个非常方便的 Map/Reduce 作业平台。巨大的优势是,所有基础设施都由 Hadoop 提供,因此您只需应用新的硬件节点来扩展。实施 Map 和 Reduce 作业应该只执行一次,在此之后,您可以为集群提供大量负载。

    【讨论】:

    • 也许下一次 :) 该应用程序已按上述方式实现。我不想重新实现整个事情并为开发人员引入新的编程模型。但 Hadoop 或 GridGain 是我肯定会研究的框架。
    【解决方案2】:

    我认为架构总体上是合理的。如果数据库在处理来自工作人员的大量并发更新时遇到问题,您可以在应用程序的另一“侧”引入第二个队列:当每个工作人员完成他们的任务时,他们将该任务的结果添加到队列。那么单个工作进程会定期从第二个队列中抓取结果对象并以大批量操作更新数据库吗?这会降低数据库的并发性,并可能提高更新的效率。

    【讨论】:

    • 在您建议的多层系统中,Pregzt 必须注意事务完整性——例如,如果持有队列的机器崩溃,[s]他可能会丢失一些数据。 JMS 确实包括事务感知,但其性能特征取决于实现。
    • 实际上我使用跨 JMS 会话和 JDBC 连接的 XA 全局事务。所以,一切都是事务性的。此外,JMS 消息也被标记为持久消息。有了这个,我可以假设一次且只有一次的交付特征。
    • 您也可以使用 Terracotta 之类的工具,它可以透明地将 JVM 堆的状态镜像到硬盘并从系统崩溃中恢复。
    【解决方案3】:

    另外,看看 Terracota 集群解决方案。

    【讨论】:

      【解决方案4】:

      对于并行处理,正如 Mork0075 所说,hadoop 是一个很好的解决方案。实际上,许多公司都将它用于非常大的日志分析。一个有趣的项目 Hive 是基于 hadoop 构建的,用于数据仓库。

      无论如何,我认为您当前的设计具有相当大的可扩展性。至于您对所有工作人员访问数据库的担忧,您可以在工作人员和数据库之间放置另一个消息队列。工作人员将处理结果放入队列中,您构建另一个程序来订阅队列并更新数据库。缺点是两个队列可能会使系统过于复杂。当然,您可以在现有的 MQ 系统中添加另一个主题。这将使系统更简单。另一种方法是使用共享文件系统,如NFS,每台worker机器将相同的目录挂载在共享文件服务器上,每个worker将其处理结果写入共享文件服务器上的单独文件中。然后您构建一个程序来检查新文件以更新数据库。在这种方法中,您引入了另一种复杂性:共享文件服务器。您可以根据自己的情况判断哪个更简单。

      【讨论】:

        【解决方案5】:

        我最近花了一些空闲时间研究 Spring Batch 2.0。这是基于 Spring 框架的新版 Java 批处理引擎。实现 Spring Batch 的人专注于此版本的并发和并行执行。我必须说它看起来很有希望!

        【讨论】:

          【解决方案6】:

          回答您的问题:

          您对此架构有何看法?你有类似的应用程序来设计吗?你当时的设计选择是什么?

          我认为这是一个很好的架构,你说得对,数据库是你的瓶颈。但是,该设计足够灵活,您可以控制数据库的输入量。

          我有跨节点的多线程工作。我不完全确定 Haddoop 或其他分布式处理系统会给你提供比你已经拥有的更多的东西,因为你只是对数据库进行 I/O。

          我已经使用 JMS 队列实现了一些类似的功能,用于集中式日志记录,它运行良好,对代码的影响比将日志写入磁盘更小。我认为它适用于您的应用程序。

          【讨论】:

            【解决方案7】:

            如果您已经在使用 Spring/Java EE,那么将 Spring Batch 作为“并发架构”的解决方案是很自然的。

            蝙蝠的两个好处:

            1. Spring Batch(从 2.0 开始)实现了分区,这意味着框架将在单独的分区步骤 (StepExecution) 中为您处理分区数据,并将这些步骤的实际执行委托给多个线程或其他分布式系统(PartitionHandlers,例如TaskExecutorPartitionHandler或更分布式的MessageChannelPartitionHandler等。)

            2. Spring 有一个很好的 OXM 包来处理 XML + Spring Batch 有一个 StaxEventItemReader,它从输入的 XML 文档中提取片段,这些片段对应于要处理的记录

            试试 Spring Batch。如果您有任何问题,请告诉我,我很乐意为您提供帮助。

            EDIT:

            同时查看Scala/AKKA Actors 和/或Scala parallel collections。如果您的任务适用于分片/分区/分布式 => 那就是 Actor 模型的用途。

            如果您想考虑非 JVM 解决方案,请查看 Erlang OTP => 简单而优雅。

            【讨论】:

              猜你喜欢
              • 2011-07-26
              • 2013-08-08
              • 2012-03-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-01-11
              • 1970-01-01
              相关资源
              最近更新 更多