【问题标题】:springbatch program does not end gracefully after batch job is completed批处理作业完成后,spring批处理程序没有正常结束
【发布时间】:2019-03-06 16:41:17
【问题描述】:

我有一个简单的 springbatch,它从 DB 读取数据并写入 eventthub。我使用 HikariCP 连接到 DB。作业完成后,我的批次没有正常结束。不知何故,HikariCP 会自行重新初始化。

11:32:55.151 [main] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
11:32:55.193 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Creating new transaction with name [org.springframework.batch.core.repository.support.SimpleJobRepository.update]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
11:32:55.194 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Acquired Connection [HikariProxyConnection@1438178266 wrapping ConnectionID:1 ClientConnectionId: ef2e5d07-0aed-417e-a571-2c9fec2fdf34] for JDBC transaction
11:32:55.194 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Switching JDBC Connection [HikariProxyConnection@1438178266 wrapping ConnectionID:1 ClientConnectionId: ef2e5d07-0aed-417e-a571-2c9fec2fdf34] to manual commit
11:32:55.236 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL query
11:32:55.236 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [SELECT VERSION FROM dse.BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
11:32:55.275 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL query
11:32:55.275 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [SELECT COUNT(*) FROM dse.BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?]
11:32:55.303 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL update
11:32:55.303 [main] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [UPDATE dse.BATCH_JOB_EXECUTION set START_TIME = ?, END_TIME = ?,  STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?]
11:32:55.339 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Initiating transaction commit
11:32:55.339 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Committing JDBC transaction on Connection [HikariProxyConnection@1438178266 wrapping ConnectionID:1 ClientConnectionId: ef2e5d07-0aed-417e-a571-2c9fec2fdf34]
11:32:55.446 [main] DEBUG o.s.j.d.DataSourceTransactionManager - Releasing JDBC Connection [HikariProxyConnection@1438178266 wrapping ConnectionID:1 ClientConnectionId: ef2e5d07-0aed-417e-a571-2c9fec2fdf34] after transaction
11:32:55.447 [main] INFO  o.s.b.c.l.support.SimpleJobLauncher - Job: [FlowJob: [name=migrateEmailJob]] completed with the following parameters: [{run.id=34}] and the following status: [COMPLETED]
11:33:19.316 [HikariPool-1 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Pool stats (total=10, active=0, idle=10, waiting=0)
11:33:49.319 [HikariPool-1 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Pool stats (total=10, active=0, idle=10, waiting=0)
11:34:19.323 [HikariPool-1 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Pool stats (total=10, active=0, idle=10, waiting=0)

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.1.3.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependency>
   <groupId>com.zaxxer</groupId>
   <artifactId>HikariCP</artifactId>
   <version>3.3.1</version>
</dependency>

【问题讨论】:

  • 您是否使用ThreadPoolTaskExecutor(或者在您的应用程序上下文中将其定义为一个bean)? Hikari 不应阻止 JVM 退出。应该还有其他需要停止的事情。
  • 不,我没有明确使用 ThreadPoolTask​​Executor。
  • 即使您不明确使用它,您也需要在工作后将其关闭。否则,你的 JVM 将不会退出。

标签: spring-batch hikaricp


【解决方案1】:

做了如下解决方法。

    public class JobCompletionNotificationListener extends JobExecutionListenerSupport {

     @Override
        public void afterJob(JobExecution jobExecution) {
            if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
                   new Thread(() -> {
                    try {
                        houseKeeping.clean();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }

//method in the housekeeping class.

public void clean() throws Exception {
        log.info("Initiate Housekeeping Task");
        Thread.sleep(delayTime);
        jdbcTemplate.getDataSource().getConnection().close();
        eventHubClient.close();
        configurableApplicationContext.close();
        System.exit(0);
    }

【讨论】:

  • 我没有看到获得新连接并在之后立即关闭它的附加价值。如果您有要关闭的数据库连接,请保留对它的引用并在 clean 方法中关闭它。此外,使用 System.exit 不会让您的 JVM 正常退出,您需要在 IMO 中删除它。关闭应用程序上下文也是如此,您需要让 Spring 关闭上下文(正确处理您的工作正在使用的其他 bean)。最后一点,我不会在作业完成后启动线程并让它休眠一段时间,您可以在当前线程中调用clean方法。
  • 总之,我认为你的afterJob 方法应该只包含eventHubClient.close();。我想这是阻止你的JVM退出的原因(除了你需要关闭的最终ThreadPoolTaskExecutor bean,如果它被定义为你的应用程序上下文即使你没有明确使用它。希望这会有所帮助!
  • 意识到我很快就发送了。如果没有 System.exit() ,hikari 池不会关闭,因此程序会挂起。
  • 关闭 eventHubClient 和 ThreadPoolTask​​Executor 仍然保持 HikariCP 运行。
  • 08:01:09.882 [Thread-16] INFO o.s.s.c.ThreadPoolTask​​Executor - 关闭 ExecutorService 'applicationTaskExecutor'.08:01:35.157 [HikariPool-1 管家] 调试 com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - 池统计信息(总计 = 20,活动 = 0,空闲 = 20,等待 = 0)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-10
  • 2018-05-22
  • 2020-08-29
  • 2019-11-16
  • 1970-01-01
相关资源
最近更新 更多