我正在使用带有 @schedule 注释的 EJB 自动计时器服务。但是我需要以下方面的帮助。
我需要一个单例时间服务(仅在集群中的一个节点上执行),但不想在服务器重新启动或崩溃期间执行错过的计时器。
我读了很多文章,但每个人都提到持久计时器来实现集群环境中的单例行为。
我的代码:
@Singleton
@Startup
public class DataService {
@Schedule(second="*/10", minute="*", hour="*", persistent=false)
public void xxxFetch() {
// business logic
}
}
有没有办法用非持久定时器实现单例服务?
最佳答案
此行为是在 EJB 3.2 规范(第 13.2.2、13.2.3、13.2.4 和 13.4.4 节)中定义的。
有两种类型的计时器,自动创建的计时器(带有注释)或以编程方式注释的计时器(使用TimerService
)。两者都可以是持久的或非持久的。
- 持久计时器(自动或以编程方式创建)将仅在一个节点中运行。
- 自动创建的非持久计时器将在集群中的每个节点上运行。
- 以编程方式创建的非持久计时器将仅在创建它们的节点上运行。
因此,要实现具有非持久计时器的单例服务,您需要设置某种配置,或者在其中一个节点上触发请求,以便以编程方式创建计时器。
但请注意,如果该节点发生故障,计时器服务将不会执行。
使用新的 Java EE 并发
规范,可以在 ManagedScheduledExecutorService
中安排任务来实现相同的行为。但在我看来,它对于使用 TimerService 以编程方式创建非持久计时器没有任何优势。恰恰相反:创建计时器是事务性操作,而安排任务则不是。
但是,Wildfly 功能可以满足您的需求:High Availability Singleton Deployments .
您可以将模块定义为单例部署。该模块部署到集群中,但仅在一个节点上处于 Activity 状态。如果该节点发生故障,该模块将在另一个节点中激活。
因此,您可以将带有自动或以编程方式创建的计时器的 EJB
放入单例模块中,这样您就可以在一个节点中执行,并获得高可用性。
关于java - 是否可以创建单例非持久性 ejb 计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65742286/