我目前正在开发一个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 问题的其他有用信息。
如何避免此类多次执行?
使用您当前的设置,您不能。您可能需要一个支持集群的调度程序。一个流行的选项是支持集群的石英调度程序。