这是问题所在
企业 Web 应用程序的用户正在执行导致长(非常长)数据库查询(或其他长处理密集型任务)的任务
问题:
- 请求超时 - 一段时间后用户可能会遇到请求超时
- 会话超时 - 如果未使用会话保持方法,则可能会发生会话超时
- Request thread lock
- 由于请求线程没有返回,它可能会阻止新的请求(如果达到池限制)
- 在某些应用程序服务器中,服务器的健康状态可能会触发节点或应用程序的强制重启(由于长时间运行的请求线程)
- If the user leaves the page:
- 交易没有被取消 - 导致无用的处理,没有人会从中受益
- 用户完成后无法返回查看结果
- 无进度指示 - 用户只需等待页面刷新
我想出了几种解决方案,但我不确定哪个更好(在各个方面,性能,最佳实践,优雅和可维护性),我想知道您推荐的解决方案是什么,以及是否有我错过了一个解决方案? (可能是的,而且很多)
糟糕的解决方案:使用请求线程作为工作线程,在会话中保存进度状态,让 AJAX 调用检查另一个并行请求中的状态(在会话中)
妥协的解决方案:创建您自己的线程池,处理监视线程、工作线程,并通过同步分布式事务缓存或持久存储中的状态来处理集群。这会释放请求,但会创建应用程序服务器不知道的线程,并且不会在取消部署时关闭。由您以干净的方式关闭线程,并且您总是有可能最终泄漏一些东西。这也不是 J2EE 的方法。
J2EE 解决方案:使用 JMS 进行异步任务,这就是它的用途
弹簧解决方案:使用 Spring 批处理
你会在你的项目中做什么/做了什么?您还知道哪些其他解决方案?您认为我上面提到的哪一个是获胜者?
我会结合你所谓的“糟糕的解决方案”和“j2ee解决方案”:
- 原始 UI 线程向“后端”发送异步 JMS 消息并返回。
- 后端接收异步请求并处理。
- 当后端到达结果(或错误)时,它会返回到控制器层。
- UI 仍然执行 AJAX 轮询或使用 Bayeux/Cometed,接收并显示结果。
技巧是匹配请求/响应对。我会这样做:
- 创建一个具有 SESSION 甚至 APPLICATION 范围的“AsyncManagerService”(AMS),以便所有线程都与同一个实例通信。
- AMS 持有一个以 id 作为键、以任意对象作为值的映射。
- 创建请求 JMS 消息时,生成一个唯一的随机密钥并将其放入消息的 jmsCorrelationId 以及映射中,其中
NULL
作为一个值。还要将该 id 传递给 UI。
- 让UI线程用之前生成的id轮询AMS只要地图中的值是
NULL
.
- 当结果准备好后,让您的 JMS 接收器将其放入 AMS 映射的给定 id 中。
- 下次 UI 线程轮询地图时,它将收到答案并停止轮询。
这是干净的,并且从任何具体领域中很好地抽象出来。纯粹的技术解决方案。
即使您不喜欢轮询,HTTP 在设计上也是无状态的,我认为这种方式轮询仅在明确定义的时间间隔内发生。
不管怎样,我用这个模式实现了一个系统,它运行得很好......
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)