通过 JMS 排队任务
Queueing tasks via JMS
我想向社区提出问题并获得尽可能多的关于我一直在思考的策略的反馈,旨在解决我项目中的一些性能问题。
上下文:
我们有一个执行 4 个步骤的重要流程。
- 实体状态变化及其持久性
- 如果1结束OK。实体被导出到 CSV 文件中。
- 如果2结束OK。实体被导出到另一个 CSV。这个有更多信息。
- 如果3结束OK。最后一个 CSV 已通过邮件发送
第 1 步和第 2 步相互关联并且非常关键。
第 3 步和第 4 步并不重要。甚至不在乎他们是否成功结束。
1-2 的性能很好,但在某些场景中 3-4 的性能非常慢。主要是第 3 步的原因。
如果我们按顺序执行所有步骤,有时步骤 3 会导致超时。客户端没有得到关于步骤 1 和 2(重要的)的任何响应,用户不知道发生了什么。
这个案例让我想到了 JMS 队列,以便将最后 2 个步骤委托给另一个 app/process。从业务逻辑中释放通知。第二次出口和邮寄将在可能时并可能并行处理。我也可以将它分成 2 个队列:导出、邮件通知。
我们的 webapp 运行在 WebLogic 11 集群中,所以我可以使用它的实现。
你觉得这个策略怎么样? WebLogic JMS 实现有什么好处吗?我应该检查另一个实现吗? ActiveMQ、RabbitMQ、...
我也在考虑使用 spring-tasks 实现 tiketing 系统。
此时我必须指向spring-batch。它的使用是有限的。我们已经有很多工作专注于重要的数据整合过程,分配更多工作的时间 window 是有限的。加上尝试一次大量处理所有项目的影响。
如果我们找到一种方法来使用 spring-batch 的多线程,也许我们可以,但我们还没有找到将我们的要求融入这种策略的方法。
提前谢谢你,请原谅我的英语。我保证会继续努力:-).
要考虑的一个问题是数据完整性。如果第 n 步失败,是否需要将第 n-1 步倒转?是否有任何您需要注意的顺序依赖性?你写的是相同的还是不同的 CSV?如果相同,则可能存在争用问题。
现在,回到最初的问题。我会考虑 Java 执行者,使用 4 个固定大小的池,并在成功发生时将任务移动到池中:
- 将第 1 步提交到 pool 1,返回一个 Future,它将用于检查是否完成。
- 第 1 步完成后,您将第 2 步提交到池 2。
- 第 2 步完成后,您现在可以 return 将结果发送给调用者。对这一点的调用一直在等待(可能有超时,所以它不会永远挂起)但现在关键任务已经完成。
- return发送给客户端后,将步骤 3 提交到池 3。
- 步骤 3 完成后,将步骤提交到池 4。
池本身虽然大小固定,但池 1/2 可以更大一些以获得最大吞吐量(并尽快返回给您的客户端),池 3/4 可以更小但仍然足够大完成工作。
您可以对 JMS 做类似的事情,但问题是相似的:您需要有多个侦听器或每个侦听器有多个线程,以便您可以以适当的速度进行处理。您可以在没有池的情况下同步执行步骤 1/2,但是这样您就无法获得执行程序为您提供的一些线程管理。您仍然需要 "schedule" 步骤 3/4 将它们放在 JMS 队列中,并且仍然有侦听器来处理它们。
从服务器宕机中恢复的能力是这里的关键,但 Executors/ExecutorService 没有持久性,所以我肯定会查看 JMS(然后我绝对会排队,甚至前 2 个步骤),但根据您的用例,它可能有点矫枉过正。
是的,消息总线使集成听起来不错的事件驱动方法。它们是异步的,所以你不会超时。当然,您将需要使用主题。当服务器中的消息过多时,WLS 会出现一些内存问题,也许不同的服务器会更好地分离关注点和资源。
我想向社区提出问题并获得尽可能多的关于我一直在思考的策略的反馈,旨在解决我项目中的一些性能问题。
上下文:
我们有一个执行 4 个步骤的重要流程。
- 实体状态变化及其持久性
- 如果1结束OK。实体被导出到 CSV 文件中。
- 如果2结束OK。实体被导出到另一个 CSV。这个有更多信息。
- 如果3结束OK。最后一个 CSV 已通过邮件发送
第 1 步和第 2 步相互关联并且非常关键。
第 3 步和第 4 步并不重要。甚至不在乎他们是否成功结束。
1-2 的性能很好,但在某些场景中 3-4 的性能非常慢。主要是第 3 步的原因。
如果我们按顺序执行所有步骤,有时步骤 3 会导致超时。客户端没有得到关于步骤 1 和 2(重要的)的任何响应,用户不知道发生了什么。
这个案例让我想到了 JMS 队列,以便将最后 2 个步骤委托给另一个 app/process。从业务逻辑中释放通知。第二次出口和邮寄将在可能时并可能并行处理。我也可以将它分成 2 个队列:导出、邮件通知。
我们的 webapp 运行在 WebLogic 11 集群中,所以我可以使用它的实现。
你觉得这个策略怎么样? WebLogic JMS 实现有什么好处吗?我应该检查另一个实现吗? ActiveMQ、RabbitMQ、...
我也在考虑使用 spring-tasks 实现 tiketing 系统。
此时我必须指向spring-batch。它的使用是有限的。我们已经有很多工作专注于重要的数据整合过程,分配更多工作的时间 window 是有限的。加上尝试一次大量处理所有项目的影响。
如果我们找到一种方法来使用 spring-batch 的多线程,也许我们可以,但我们还没有找到将我们的要求融入这种策略的方法。
提前谢谢你,请原谅我的英语。我保证会继续努力:-).
要考虑的一个问题是数据完整性。如果第 n 步失败,是否需要将第 n-1 步倒转?是否有任何您需要注意的顺序依赖性?你写的是相同的还是不同的 CSV?如果相同,则可能存在争用问题。
现在,回到最初的问题。我会考虑 Java 执行者,使用 4 个固定大小的池,并在成功发生时将任务移动到池中:
- 将第 1 步提交到 pool 1,返回一个 Future,它将用于检查是否完成。
- 第 1 步完成后,您将第 2 步提交到池 2。
- 第 2 步完成后,您现在可以 return 将结果发送给调用者。对这一点的调用一直在等待(可能有超时,所以它不会永远挂起)但现在关键任务已经完成。
- return发送给客户端后,将步骤 3 提交到池 3。
- 步骤 3 完成后,将步骤提交到池 4。
池本身虽然大小固定,但池 1/2 可以更大一些以获得最大吞吐量(并尽快返回给您的客户端),池 3/4 可以更小但仍然足够大完成工作。
您可以对 JMS 做类似的事情,但问题是相似的:您需要有多个侦听器或每个侦听器有多个线程,以便您可以以适当的速度进行处理。您可以在没有池的情况下同步执行步骤 1/2,但是这样您就无法获得执行程序为您提供的一些线程管理。您仍然需要 "schedule" 步骤 3/4 将它们放在 JMS 队列中,并且仍然有侦听器来处理它们。
从服务器宕机中恢复的能力是这里的关键,但 Executors/ExecutorService 没有持久性,所以我肯定会查看 JMS(然后我绝对会排队,甚至前 2 个步骤),但根据您的用例,它可能有点矫枉过正。
是的,消息总线使集成听起来不错的事件驱动方法。它们是异步的,所以你不会超时。当然,您将需要使用主题。当服务器中的消息过多时,WLS 会出现一些内存问题,也许不同的服务器会更好地分离关注点和资源。