java - EJB 如何并行化一个长时间的 CPU 密集型进程?

标签 java architecture ejb parallel-processing

该应用程序有一个 CPU 密集型长进程,当前在一个服务器上连续运行(一种 EJB 方法),当客户端请求它时。

理论上可以(从概念的角度)将该进程拆分为 N 个 block 并并行执行它们,只要可以收集所有并行作业的输出并将其连接在一起,然后再将其发送回客户端启动了这个过程。我想使用这种并行化来优化性能。

如何使用 EJB 实现这种并行化?我知道我们不应该在 EJB 方法中创建线程。相反,我们应该发布消息(每个作业一个)以供消息驱动的 bean (MDB) 使用。但那样就不再是同步调用了。在这种情况下,同步似乎是一项要求,因为我需要在将所有作业的输出发送回客户端之前收集它。

有解决办法吗?

最佳答案

有各种各样的方法可以做到这一点。

第一,您可以使用 EJB 计时器来创建将立即启动的一次性进程。这是在后台生成进程的好方法。 EJB 计时器与特定的 session Bean 实现相关联。您可以将 EJB 计时器添加到您希望能够执行此操作的每个 session Bean,或者您可以拥有一个 session Bean,然后可以通过某种调度机制调用您的应用程序逻辑。

对我来说,我将一个可序列化的参数 block 连同一个满足特定接口(interface)的类名传递给一个通用的 session Bean,然后由该 session Bean 执行该类。这样我就可以很容易地为任何东西做背景。

关于 EJB 计时器的一个警告是 EJB 计时器是持久的。一旦你创建了一个 EJB 定时器,它就会留在容器中,直到它的工作完成或被取消。问题在于,如果您有一个长时间运行的进程,并且服务器出现故障,当它重新启动时,该进程将继续并恢复运行。请注意,这可能是一件好事,但前提是您的流程准备好重新启动。但是,如果您有一个遍历“10,000 个项目”的简单过程,如果服务器在第 9,999 个项目上出现故障,当它恢复时,您可以轻松地看到它只是从第 1 个项目重新开始。这一切都是可行的,只是需要注意的。

另一种后台处理方式是使用 JMS 队列。将一条消息放入队列,处理程序将与您的应用程序的其余部分同步运行。

这里最聪明的部分,也是我利用 Timer Bean 所做的事情,是您可以根据您将系统配置为拥有多少 MDB 实例来控制将运行多少“作业”。

因此,对于在多个并行 block 中运行进程的特定任务,我接受任务,将其分解为“片段”,然后将每个片段发送到消息队列,MDB 将在其中执行它们。如果我允许 10 个 MDB 实例,我可以同时运行任何任务的 10 个“部分”。

这实际上效果出奇地好。将进程拆分并通过 JMS 队列路由它会产生一些开销,但这基本上就是“启动时间”。一旦开始,您将获得真正的好处。

使用 Message Queue 的另一个好处是您可以让实际的长时间运行的进程在单独的机器上执行,或者您可以轻松地创建一个机器集群来处理这些进程。然而,界面是一样的,代码不知道有什么区别。

我发现,一旦您将长时间运行的进程降级到后台,您就会付出代价,即无法即时访问该进程。也就是说,没有理由直接监控正在执行的类本身,只是让它们将有趣的信息和统计信息发布到数据库或 JMX 或其他任何东西,而不是拥有可以直接监控对象的东西,因为它共享相同的内存空间。

我能够轻松地设置一个框架,让任务在 EJB 计时器或 MDB 分散队列上运行,任务是相同的,我可以监视它们的进度、停止它们等。

您可以结合分散技术来创建多个 EJB 计时器作业。 MDB 的免费优势之一是它充当线程池,可以限制您的作业(因此您不会突然让您的系统因过多的后台进程而饱和)。您只需利用容器中的 EJB 管理功能即可“免费”获得此功能。

最后,Java EE 6 为 session Bean 方法提供了一个新的“异步”(或其他)限定符。我不知道这是如何工作的细节,因为我还没有使用过新的 Java EE 6 容器。但我想您可能不想只为这个设施更换容器。

关于java - EJB 如何并行化一个长时间的 CPU 密集型进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2005934/

相关文章:

java - Spring Security 中的访问总是被拒绝 - DenyAllPermissionEvaluator

java - 这个例子中 Java 的返回类型是怎么回事

ios - 阻止回调或协议(protocol)在 VIPER 中的 DataManager 和交互器之间传递信息?

web-services - 是否可以在 GlassFish 3.1 上为无状态 ejb Web 服务定义 servlet 过滤器

java - Android WebView 无法在 WebRTC 对等连接上显示两个视频标签

java - 生命游戏未正确重置

.net - WPF/Silverlight - Prism - 初学者资源

architecture - SemVer 和微服务

java - 当我从 CDI 支持 bean 调用 EJB Dao 时,返回实体中的 @OneToMany 集合将被清除并为空

java - EJB Bean 与不同的未完成事务关联