Jakarta ee 运行多次的Java计时器服务
我创建了一个函数Jakarta ee 运行多次的Java计时器服务,jakarta-ee,timer,scheduling,Jakarta Ee,Timer,Scheduling,我创建了一个函数doWork(),该函数计划在每天凌晨1:00运行,函数如下: @Schedule(hour = "1", persistent = false) public void doWork() { System.out.println("Starting .....\nTIME: " + System.currentTimeMillis()); System.out.println("this : " + this);
doWork()
,该函数计划在每天凌晨1:00运行,函数如下:
@Schedule(hour = "1", persistent = false)
public void doWork()
{
System.out.println("Starting .....\nTIME: " + System.currentTimeMillis());
System.out.println("this : " + this);
//Some code here, if-conditions and try/catch blocks. No loops
System.out.println("Exiting .....\nTIME: " + System.currentTimeMillis());
System.out.println("this : " + this);
}
问题是此函数运行多次,而不是按计划运行
一旦我创建了它,它就完全按照预期运行(每天凌晨1:00)。几天后,它在1:03:00开始运行(这没有任何意义,因为它是非持久性的,而且服务器中也没有宕机)。在此之后,功能开始运行多次,间隔很短(秒差)
有人知道这可能是什么原因吗,或者告诉我我能做些什么来修复它
[编辑]:
环境详情
应用服务器:WebSphereApplicationServer8.5.5
IDE:RationalApplicationDeveloper9.1
数据库管理系统:IBM DB2 10.1我相信您正在观察容器试图重试失败的
doWork()
调用
EJB计时器服务是事务性的
如果超时方法的执行引发任何运行时异常,则事务将回滚,容器将再次尝试执行超时方法。参见EJB 3.1规范的§18.2.8事务
此外,如果事务超时过期,一些实现只会将当前事务标记为回滚并继续处理。这将导致计时器调用最终失败,并将尝试重试
这种重试机制没有很好地指定,实际行为因实现而异。有些人会永远重试,有些人会在多次尝试后放弃。例如,WebSphere提供了一种指定重试策略的方法。看
最后,如果您的应用程序跨多个节点运行,那么每个服务器实例可能都有一个计时器。根据规范§18.2.3非持续计时器:
对于自动非持久计时器,容器在应用程序初始化期间为容器分布的每个JVM创建一个新的非持久计时器
如果这些服务器都在执行相同的任务,那么这可能会导致足够的混乱,从而产生错误、回滚和后续重试。您使用的是哪个应用程序服务器(和版本)?这可能有助于检查是否存在与此相关的问题。您如何记录服务运行的时间?日志输出?系统/服务器时间?@OlivierGrégoire我正在使用WebSphereApplicationServer8.5。5@kolossus这两个时间都是根据服务器时间记录的。该方法计划在凌晨1:00运行,但由于某些原因,它在随机时间运行,并运行多次。根据日志,doWork()方法第一次成功运行,然后再次运行并失败,并继续重试。它所做的是获取一个csv文件,对其进行解析,从数据库中删除所有内容,然后保存解析后的数据。根据日志,在第一次尝试时,数据库被清空并成功重新填充,然后该方法再次运行并不断重试,最后我得到一个空数据库。由于第一次尝试是成功的,我不明白为什么在第一次尝试后会再次调用该方法?在任何人可以进一步推测之前,您仍然需要提供您的环境的更多细节。此外,您如何确保初始事务成功完成?即
doWork()
退出后?由于日志记录,我确信它在第一次尝试时成功完成。通过检查数据库日志,我可以看到已解析的.csv文件中的记录已成功保存到数据库中。然后它继续重试,删除数据库中的所有内容,最后得到一个空数据库。请检查编辑环境详细信息显示您有多少服务器实例?EJB是@Singleton还是@Stateless?执行该方法需要多长时间?