b.r*_*oth 13 java architecture parallel-processing ejb
该应用程序具有CPU密集型长进程,当客户端请求时,该进程当前在一个服务器(EJB方法)上串行运行.
理论上可以(从概念的角度)将该进程拆分为N个块并并行执行它们,只要可以收集并连接所有并行作业的输出,然后再将其发送回发起进程的客户端.我想使用这种并行化来优化性能.
如何使用EJB实现此并行化?我知道我们不应该在EJB方法中创建线程.相反,我们应该发布消息驱动bean(MDB)消息(每个作业一个).但那时它不再是同步通话了.在这种情况下,同步似乎是一个要求,因为我需要在将所有作业的输出发送回客户端之前收集它们的输出.
这有解决方案吗?
Wil*_*ung 10
有各种各样的方法可以做到这一点.
一,您可以使用EJB Timer创建一个立即启动的一次运行进程.这是在后台生成进程的好方法.EJB Timer与特定的Session Bean实现相关联.您可以将EJB计时器添加到您希望能够执行此操作的每个会话Bean,也可以使用单个会话Bean,然后可以通过某种调度机制调用应用程序逻辑.
对我来说,我传递了一个可序列化的blob参数以及一个符合特定接口的类名,然后执行该类的通用会话Bean.通过这种方式,我可以轻松地背景大部
关于EJB Timer的一个警告是EJB Timers是持久的.创建EJB计时器后,它将保留在容器中,直到其作业完成或取消.问题在于如果你有一个长时间运行的进程,并且服务器出现故障,当它重新启动时,进程将继续并重新启动.请注意,这可能是一件好事,但前提是您的流程已准备好重新启动.但是如果你有一个简单的过程迭代"10,000项",如果服务器在第9,999项下降,当它恢复时,你可以很容易地看到它只是从第1项开始.这一切都是可行的,只是需要注意的警告的.
另一种背景的方法是你可以使用JMS队列.在队列上放置一条消息,处理程序从应用程序的其余部分运行.
这里聪明的部分,以及我利用Timer Bean的工作做的事情,你可以控制根据配置系统的MDB实例数量来运行多少"作业".
因此,对于以多个并行块运行进程的特定任务,我执行任务,将其分解为"片段",然后在消息队列中发送每个片段,MDB在其中执行它们.如果我允许10个MDB实例,我可以同时运行任何任务的10个"部分".
这实际上运作得非常好.将进程分解并通过JMS队列进行路由会产生一些开销,但这基本上都是"启动时间".一旦它开始,你将获得真正的好处.
使用Message Queue的另一个好处是,您可以在单独的计算机上执行实际长时间运行的进程,或者您可以轻松创建一组计算机来处理这些进程.然而,界面是相同的,代码不知道差异.
我发现,一旦你将一个长时间运行的流程降级到后台,你就可以为那个流程的即时访问权限付出代价.也就是说,没有理由直接监视执行类本身,只是让它们向数据库或JMX或其他任何东西发布有趣的信息和统计信息,而不是直接监视对象,因为它共享相同的内存空间.
我很容易设置一个框架,允许任务在EJB Timer或MDB分散队列上运行,任务是相同的,我可以监视他们的进度,停止他们等等.
您可以组合分散技术来创建多个EJB Timer作业.MDB的一个免费优势是它充当线程池,可以限制您的工作(因此您不会因为太多的后台进程而突然使您的系统饱和).只需通过利用容器中的EJB管理功能,您就可以"免费"获得此功能.
最后,Java EE 6为Session Bean方法提供了一个新的"异步"(或某种)限定符.我不知道它是如何工作的细节,因为我还没有使用新的Java EE 6容器.但我想你可能不会想要为这个设施更换容器.
这个特殊问题已经出现过多次,我将总结出几种可能的解决方案,其中只有一种我会推荐.
使用commonj API中的WorkManager.它允许Java EE容器中的托管线程,并且专门设计用于适合您的用例.如果您使用的是WebSphere或WebLogic,则这些API已在您的服务器中可用.对于其他人,您必须自己提供第三方解决方案.
相关问题 为什么不鼓励产生线程