是否可以创建 Singleton 非持久性 ejb 计时器?

is it possible to create Singleton non-persistent ejb timer?

我正在使用带有@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)。两者都可以是持久的或非持久的。

  • 持久性计时器(自动或以编程方式创建)将 运行 仅在一个节点中。
  • 非持久性自动创建的计时器将 运行 在集群中的每个节点上。
  • 以编程方式创建的非持久计时器将 运行 仅在它们创建的节点上。

因此,要实现具有非持久计时器的单例服务,您需要设置某种配置,或在其中一个节点上触发请求,以便它以编程方式创建计时器。

但请注意,如果该节点发生故障,则定时器服务将不会执行。

使用新的 Concurrency for Java EE 规范在 ManagedScheduledExecutorService 中安排任务可以实现相同的行为。但在 IMO 中,使用 TimerService 以编程方式创建非持久性计时器没有任何优势。恰恰相反:创建计时器是事务性操作,而调度任务则不是。

但是有一个 Wildfly 功能可以满足您的需求:High Availability Singleton Deployments

您可以将模块定义为单例部署。此模块已部署到集群,但仅在一个节点上处于活动状态。如果该节点出现故障,该模块将在另一个节点中激活。

因此,您可以将 EJB 与自动或以编程方式创建的计时器放在一个单例模块中,这样您就可以在一个节点中执行并获得高可用性。