我有一个系统应该获取包含文档的大文件并处理这些文件以拆分单个文档并创建要使用 JPA 持久保存的文档对象(或者至少在这个问题中假设它)。
每个文件中的文件在 1 文档到 100 000 的范围内。这些文件有多种类型
现在最担心的是规范禁止访问本地文件。至少以我习惯的方式。
我可以将文件保存到数据库表中,但这真的是个好方法吗?文件最大可达 2GB ,从数据库访问文件需要将整个文件下载到内存或磁盘上。
我的第一个想法是将这个过程从应用服务器中分离出来,并使用更传统的方法,但我一直在考虑如何将它保留在应用服务器上以用于将来的目的,例如集群等。
我的问题基本上是
- 在 Java EE 中是否有处理此问题的标准方法或推荐方法?
- 是否有特定于应用程序服务器的方法来解决这个问题?
- 您能否证明将此过程从应用程序服务器中分离出来是合理的? 您将如何设计这两个独立系统之间的通信 channel ?
我在这里勾勒出更多的命题并考虑以下问题:
- 可扩展性(文件大小、集群等)
- 批处理架构(作业恢复、错误处理、监控等)
- 符合 J2EE
使用 JCA
JCA 连接器属于 Java EE 堆栈,允许来自/到 EJB 世界的入站/出站连接。 JDBC 和 JMS 通常作为 JCA 连接器实现。入站 JCA 连接器可以使用线程(通过 worker 抽象)和事务。然后它可以将任何处理转发给消息驱动的 bean (MDB)。
- 编写一个轮询新文件的 JCA 连接器,然后处理它们并以同步方式将进一步的处理委托(delegate)给消息驱动的 bean。
- 然后 MDB 可以使用 JPA 将信息持久化到数据库中
- JCA 连接器控制事务,多个 MDB 调用可以在同一个事务中
- 文件系统不是事务性的,因此您需要弄清楚如何处理错误,例如错误的输入文件
- 您可能可以在整个管道中使用流式传输 (InputStream)
普通线程
我们可以使用从 Web servlet 上下文监听器(或 evt。EJB 计时器)启动的线程,实现与 JCA 方式大致相同的效果。
- 线程轮询新文件,如果找到文件,它会处理它并以同步方式将进一步处理委托(delegate)给常规 SLSB。
- Web 容器中的线程可以访问 UserTransaction 并可以控制事务
- EJB 可以是本地的,以便通过引用传递 InputStream
- web模块+ejb的部署,耳听为虚
使用 JMS
为避免多个并发轮询线程的需要和作业获取/锁定的问题,实际处理可以使用JMS 异步实现。 JMS 也很有趣,可以将处理拆分为更小的任务。
- 定期任务轮询新文件。如果找到文件,JMS 消息将排队。
- 当 JMS 消息传递时,读取和处理文件,并使用 JPA 将信息持久化到数据库中
- 如果 JMS 处理失败,应用程序。服务器可能会自动重试或将消息放入死消息队列
- 监控/错误处理更复杂
- 你或许可以使用流媒体
使用 ESB
在过去的一年里出现了许多处理集成的项目:JBI、ServiceMix、OpenESB、Mule、Spring 集成、Java CAPS、BPEL。有些是技术,有些是平台,它们之间有一些重叠。它们都有一大堆连接器来路由、转换和编排消息流。恕我直言,消息被认为是一小段信息,可能很难使用这些技术来处理您的大数据文件。网址patterns of enterprise application integration是获取更多信息的绝佳网站。
IMO,最适合 Java EE 哲学的方法是 JCA。但是投入的力度比较大。在您的情况下,使用将进一步处理委托(delegate)给 SLSB 的普通线程可能是最简单的解决方案。如果处理管道变得更加复杂,JMS 方法(接近 P. Thivent 的提议)可能会很有趣。使用 ESB 对我来说似乎有些过分了。