Java EJB如何并行化一个长的CPU密集型进程?

Java EJB如何并行化一个长的CPU密集型进程?,java,architecture,ejb,parallel-processing,Java,Architecture,Ejb,Parallel Processing,应用程序有一个CPU密集型长进程,当前当客户端请求时,该进程在一台服务器(EJB方法)上串行运行 从理论上讲,可以(从概念的角度)将该进程分成N个块并并行执行,只要所有并行作业的输出都可以在发送回启动该进程的客户端之前收集并合并在一起。我想使用这种并行化来优化性能 如何用EJB实现这种并行化?我知道我们不应该在EJB方法中创建线程。相反,我们应该发布消息(每个作业一条)供消息驱动bean(MDB)使用。但这样就不再是同步调用了。在这种情况下,同步似乎是一项要求,因为我需要在将所有作业的输出发送回

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

从理论上讲,可以(从概念的角度)将该进程分成N个块并并行执行,只要所有并行作业的输出都可以在发送回启动该进程的客户端之前收集并合并在一起。我想使用这种并行化来优化性能

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


有解决方案吗?

我曾经参与过一个项目,其中EJB事务一次最多运行5个小时。啊

这个应用程序还有一位BEA专家顾问,他批准他们从事务中启动额外的线程。虽然它在规范和其他地方不被推荐,但它不会自动导致失败。您需要知道,您的额外线程不在容器的控制范围内,因此,如果出现问题,那是您的错。但是,如果您可以确保在最坏情况下启动的线程数量不超过合理的限制,并且它们都在合理的时间内完全终止,那么这样工作是完全可能的。事实上,对你来说,这似乎是唯一的解决办法

有一些稍微深奥的解决方案是可能的,您的EJB应用程序向另一个应用程序提供服务,然后该应用程序在返回EJB调用程序之前自己执行多线程处理。但这本质上只是在转移问题


您可以考虑线程池解决方案,以保持线程生成的线程数的上限。如果你有太多线程,你的应用程序就会表现得很糟糕。

你已经很好地分析了这种情况,不,没有与EJB模型相匹配的模式

创建线程主要是被禁止的,因为它绕过了应用程序。服务器线程管理策略,也因为事务

我在一个有类似要求的项目上工作,我决定产生额外的线程(与sepc相反)。要并行化的操作是只读的,因此它与事务相关(线程基本上没有与之关联的事务)。我也知道我不会在每次EJB调用中产生太多线程,所以线程的数量不是问题。但是,如果线程应该修改数据,那么就严重破坏了EJB的事务模型。但是如果你的操作是纯计算的话,那可能没问题


希望它有帮助……

EJB最终是提供请求/应答语义的客户机-服务器系统的事务组件。如果您发现自己需要在请求/应答周期的范围内将一个长期运行的事务归档,那么您的系统架构师(ure)在某个地方走错了方向


您描述的情况由一个带有消息传递后端的基于事件的体系结构干净、正确地处理。初始事件启动流程(然后可以通过让工作人员订阅事件主题来实现简单的并行化),聚合流程本身在完成时引发一个事件。您仍然可以在请求/应答周期的范围内压缩这些序列,但是您必然会违反JavaEE系统体系结构规范的文字和精神

这个问题已经多次出现,我将总结出几种可能的解决方案,我只推荐其中一种

使用commonj API中的WorkManager。它允许JavaEE容器中的托管线程,并专门设计为适合您的用例。如果您使用的是WebSphere或WebLogic,那么这些API在您的服务器中已经可用。对于其他人,你必须在自己身上加入第三方解决方案

相关问题
有各种各样的方法可以做到这一点

首先,您可以使用EJB计时器创建一个立即启动的一次性运行进程。这是一种在后台生成进程的好技术。EJB计时器与特定会话Bean实现相关联。您可以向每个会话Bean添加一个EJB计时器,您希望能够做到这一点,或者您可以有一个会话Bean,然后通过某种调度机制调用您的应用程序逻辑

对我来说,我将一组可序列化的参数以及满足特定接口的类名传递给一个通用会话Bean,然后执行该类。这样我就可以轻松地为大多数事情添加背景

关于EJB计时器的一个警告是EJB计时器是持久的。一旦创建了EJB计时器,它将一直留在容器中,直到其作业完成或取消。这个问题的关键在于,如果您有一个长时间运行的进程,并且服务器停机,当它重新启动时,该进程将继续并恢复。请注意,这可能是一件好事,但前提是您的进程准备重新启动。但是,如果您有一个简单的过程迭代“10000个项目”,如果服务器在项目9999上停机,当它返回时,您可以很容易地看到它只是从项目1开始。这一切都是可行的,只是需要注意一点

另一种方法是使用JMS队列。在队列上放置一条消息,处理程序将从应用程序的其余部分同步运行

这里有一个聪明的部分,我也做了一些事情来利用这项工作