我正在用Thorntail编写计划任务,该任务将运行很长时间(大约30分钟)。但是,Thorntail似乎将执行时间限制为30秒。
我的代码看起来像这样(我删除了我认为不相关的代码):
@Singleton
public class ReportJobProcessor {
@Schedule(hour = "*", minute = "*/30", persistent = false)
public void processJobs() {
// Acquire a list of jobs
jobs.forEach(this::processJob);
}
private void processJob(ReportJob job) {
// A long running process
}
}
[30秒后,我在日志中看到以下内容:
2019-10-01 16:15:14,097信息[org.jboss.as.ejb3.timer](EJB默认-2)WFLYEJB0021:计时器:[id = ... timedObjectId = ...自动计时器?: true持久吗?:false timerService=org.jboss.as.ejb3.timerservice.TimerServiceImpl@42478b98 initialExpiration = null intervalDuration(以毫秒为单位)= 0 nextExpiration = Tue Oct 01 16:20:00 CEST 2019 timerState = IN_TIMEOUT info = null]将重试
再过30秒,由于作业仍未完成而引发异常。
我不知道如何增加超时时间,谷歌搜索我的问题没有任何帮助。
如何将超时时间增加到30秒以上?
我建议您采取一些不同的方法。
调度的任务会将作业分配给名为ReportJobExecutor
的异步运行的无状态会话Bean(SLSB),并在作业分配后立即完成而不会超时。同时运行的SLSB的数量可以在project-defaults.yml
中进行调整,默认计数为16,IIRC。这是一个非常基本的示例,但是演示了使用预定义bean池的Java EE执行,该预定义bean池是使用EJB Timer调用的。更为复杂的示例是手动合并执行程序,这将使您能够控制执行程序的生命周期(例如,在指定时间后将其杀死)。
@Singleton
public class ReportJobProcessor {
@Inject ReportJobExecutor reportJobExecutor;
@Schedule(hour = "*", minute = "*/30", persistent = false)
public void processJobs() {
// Acquire a list of jobs
jobs.forEach(job -> reportJobExecutor.run(job));
}
}
@Stateless
@Asynchronous
public class ReportJobExecutor {
public void run(ReportJob job) {
//do whatever with job
}
}
想法#2:另一种方法是使用Java批处理API(JSR 352),很遗憾,我对该API并不熟悉。