在集群 Java EE 应用程序中作为@Singleton实现的计划任务的并行化



我目前正在开发一个Java EE应用程序,它将部署在Payara服务器4上。payara 服务器在主机 1 上运行,还有 2 个实例(主机 1 和主机 2(可用作 Payara 集群。

我遇到的问题是,如果我们在单例类中调度一个任务,那么该任务将同时执行三次。问题是两个方面的。

  • 为什么会出现这种现象?
  • 如何避免此类多次执行?

入口点如下所示。(不是全部。

@ApplicationScoped
@Singleton
public class StartClass {
public void StartClass() {}
public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext) throws ... { ... }
@Schedule(hour="*", minute="0", persistent=false)
public void runJob() {
MyClass my_class = new MyClass();
my_class.do_the_job();
}
}

在这里,我上面提到的计划任务是my_class.do_the_job()。这种方法只是在数据库中插入一行,源代码与本教程非常相似,并且有几个System.out.println("DO_THE_JOB")。目标表有一列,该列会自动填充插入的时间戳。我还放了一个关于主机的信息,System.getenv("HOST")。结果是我们每小时插入三行:主机 1 的 2 行和主机 2 的 1 行。但是println()的结果可以在日志文件中找到一次。

笔记:

  • JTA的使用不是重点。我想了解应用程序和集群的行为。
  • Java 版本是 8
  • 如果应该有另一个相关部分,请告诉我。

在 JEE 规范中,没有办法有一个集群范围的@Singleton

解决此问题的一种可能选项是使用特定于 Payara 的群集单例和附加@Clustered注释。它从Payara 4.182开始可用。

在此处阅读更多相关信息 Payara 集群单例

为什么会出现这种现象?

仅仅因为单例bean 不可群集。这意味着群集的每个节点都有自己的StartClass实例。您可能会找到有关类似 SO 问题的其他有用信息。

如何避免此类多次执行?

使用您当前的设置,您不能。您可能需要一个支持集群的调度程序。一个流行的选项是支持集群的石英调度程序。

最新更新