WAR 版本更改后运行 EJB 持久计时器

Posted

技术标签:

【中文标题】WAR 版本更改后运行 EJB 持久计时器【英文标题】:Running EJB persistent timer after WAR version change 【发布时间】:2021-10-19 02:53:39 【问题描述】:

我有一个应用程序,它以独立模式在Wildfly-18 上运行持久计时器。这些只是由Timerservice 触发。

@Stateless
class MyTimerService 

    @Resource
    private TimerService timerService;

    public void registerTimer() 
        TimerConfig timerConfig = new TimerConfig("identifier", true);
        timerService.createSingleActionTimer(executionDate, timerConfig);
    

    @Timeout
    void timeoutTimer(Timer timer) 
        // Do stuff
    

从本质上讲,这可以正常工作,直到发布新版本。这是因为他们的documentation 中所述的以下内容:

持久性计时器将由 EAR 的名称、子部署 JAR 的名称和 Bean 的名称来标识。 如果其中一个名称被更改(例如 EAR 名称包含一个版本),则计时器条目将成为孤立的并且将不再触发计时器事件。

所以在新版本发布后,data 文件夹中会有一个新文件夹。但是旧的计时器是孤立的,不再执行。

wildfly-18.0.1/standalone/data/timer-service-data
├───my-application-1.0.0.my-application-1.0.0.MyTimerService
│       6a14484b-3a62-4345-bcc2-1507ca9b6223.xml
│
└───my-application-1.0.1.my-application-1.0.1.MyTimerService

看起来您只能更改查看 model-reference 的***文件夹 (timer-service-data)。但并不是每个新版本都是一个新文件夹。

我们希望将版本名称保留在 war 中。有没有办法在新版本之后继续引用同一个文件夹?还是运行旧的孤立计时器?

【问题讨论】:

为什么?旧计时器已弃用(不再存在)。 @josejuan 我不会说它已被弃用。如果某个活动计划在 5 天内运行,而我今天发布了一个新版本,我仍然希望该活动在预定的时间运行。无论我只是重新启动服务器还是部署新版本,它仍然计划运行。 你以前的版本也部署了吗? (无论如何,在我看来,这种策略是一种反模式) @josejuan 不,只部署了 1 个版本。最新的。如果 V1 创建了一个计时器,V2 应该仍然能够执行它。否则持久计时器对我来说毫无意义,除非你从不重命名你的战争。 一些想法以防万一:首先,您真的需要文件名中的版本吗?其次,如果使用某种管道进行部署,您可以添加一个步骤,将 xml 文件从旧文件夹移动(或复制)到新文件夹。 也许 - 只是也许就足够了,而且在实现和耦合方面非常便宜。然后,也许在部署过程中再次尝试根据旧的内容重新创建新的 xml 文件,即读取旧的并自己编写新的。祝你好运! 【参考方案1】:

持久性计时器仅在服务重新启动而不是在代码库重新部署下(特别是在工件版本更改下)是持久性的。

来自documentation:

另外,请注意,EJB 持久计时器与基于应用程序名称、模块名称和 bean 名称的 EJB 相关联。如果更新了应用程序,并且这些名称中的任何一个发生了更改,则计时器继续存在于数据库中,但似乎不再存在,因为它不再过期并运行。

我的建议是您将任何基础架构状态视为易失性(除了那些特别持久的,例如文件系统、数据库等......并且已完成安全状态管理)。

对于这种特殊情况,当系统重新启动时,您可以检查哪些Timers 已挂起并重新配置它们,但是,我的建议是使用特定的排队策略(例如,某些 *MQ 中的优先队列)。这将使其对服务故障具有弹性,可以并行处理、分布式处理、自动缩放等......

【讨论】:

以上是关于WAR 版本更改后运行 EJB 持久计时器的主要内容,如果未能解决你的问题,请参考以下文章

EJB 定时器服务线程安全吗?

如何停止无尽的 EJB 3 计时器?

如何为vertx设置一个持久的计时器,如果服务器重新启动,它不会丢失?

java ejb TimerService:getTimers返回的已取消计时器(树脂caucho)

EJB 教程推荐

EJB3.0 定时服务:Timer Service