我有一个长时间运行的任务,需要几个小时才能完成。运行批处理作业的框与批处理数据库之间存在防火墙。该防火墙上的不活动超时为两个小时,我们的网络团队不愿意改变这一点。因此,当长时间运行的 tasklet 完成并且 Spring Batch 使用状态更新数据库时,它会失败,因为防火墙已经由于不活动而切断了连接。关于如何解决这个问题的任何想法?
这是我的数据源:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin@db_url" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
更多背景信息。此任务包不使用此数据库连接。只有Spring Batch正在使用它。tasklet 作业是监视队列,并在队列为空后完成下一步。这种队列消耗可能需要数小时。
更新:我尝试添加Oracle TCP保持活动状态,但它仍然超时。
<property name="url" value="jdbc:oracle:thin:@(DESCRIPTION=(ENABLE=BROKEN)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=port)))(CONNECT_DATA=(SID=sidname)))" />
谢谢。布莱恩
不确定您的tasklet是否真的需要事务,但就我而言,我能够通过定义事务属性来解决问题:
@Bean
public Step myStep(StepBuilderFactory stepBuilderFactory, MyTasklet myTasklet) {
return stepBuilderFactory.get("myStep").tasklet(myTasklet).transactionAttribute(new DefaultTransactionAttribute(TransactionAttribute.PROPAGATION_NEVER)).build();
}
如果你想杀死长时间运行的作业,那么有两种方法:
- 作业中断政策
- 命令行运行程序
我们可以使用 JobInterruptedPolicy 以编程方式终止作业,也可以使用 CommandLineRunner 手动终止作业,方法是将命令输出到 STOP。
作业中断政策
-
使用 JobOperator。停止作业
SimpleJobOperator jobOperator = new SimpleJobOperator(); jobOperator.setJobRepository(jobRepository); jobOperator.setJobLauncher(jobLauncher); jobOperator.setJobExplorer(jobExplorer); jobOperator.setJobRegistry(jobRegistry); //If you know job execution id that you want to stop the job jobOperator.stop(exceutionId);
如果你 有jobExceution对象,你可以简单地使用JobExceution.stop()方法。
以上这两种方法都成功地为我工作。
BATCH_JOB_EXECUTION弹簧批次表
批处理状态:已停止
退出状态:已停止