Spring Batch每次运行2小时10分钟即终止,归档未完成求助
Spring Batch归档任务固定时长后突然终止问题排查
我编写了一个仅包含Reader和Writer(无Processor)的Spring Batch程序,功能是根据Reader读取的输入记录,将源表部分数据加载至归档表。在Writer中调用了存储过程,负责将记录归档到目标表并删除源表对应数据。但遇到异常:每次启动批处理后,进程都会在运行2小时10分钟时突然终止,重新运行结果一致,且归档并未完成。日志中无报错信息,仅输出以下内容:
2022-08-29 17:12:09.157 INFO 9109612 --- [SpringApplicationShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2022-08-29 17:12:09.158 TRACE 9109612 --- [SpringApplicationShutdownHook] o.h.type.spi.TypeConfiguration$Scope : Handling #sessionFactoryClosed from [org.hibernate.internal.SessionFactoryImpl@c647c96f] for TypeConfiguration 2022-08-29 17:12:09.158 DEBUG 9109612 --- [SpringApplicationShutdownHook] o.h.type.spi.TypeConfiguration$Scope : Un-scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration$Scope@9239dddd] from SessionFactory [org.hibernate.internal.SessionFactoryImpl@c647c96f]
以下是Batch Writer的实现代码:
@Override public void write(List<? extends Account> items) throws Exception { DataSource dataSource= (DataSource) ctx.getBean("dataSource"); this.jdbcTemplate = new JdbcTemplate(dataSource); for (cvObj : items) { logger.info("Going to archive for batch "); jdbcTemplate.update(QUERY_INSERT_ARCHIVE,cvObj.getRunner()); jdbcTemplate.update("{ call pArchiveRecords (?) }", cvObj.getRunner()); logger.info("Archival completed for ::: "+cvObj.getRunner()); jdbcTemplate.update(QUERY_UPDATE_ARCHIVE,cvObj.getRunner()); } }
可能的原因及排查方向:
- 系统/容器超时限制:固定时长终止大概率是配置的超时阈值触发。检查服务器的进程运行时长限制、容器(如K8s、Tomcat)的存活/终止策略,或是操作系统的cgroup、ulimit等资源限制配置。
- 数据库连接相关超时:查看数据库连接池的
maxWait、validationTimeout等参数,以及数据库端的连接超时设置。若存储过程执行过久或连接池资源耗尽,可能触发上下文关闭。 - Spring Batch任务超时配置:检查Job或Step层面是否设置了
timeout属性,比如@Step注解的timeout参数,是否刚好匹配2小时10分钟的时长。 - 资源耗尽被系统杀死:长时间运行的批量任务可能耗尽内存、CPU,触发操作系统OOM Killer终止进程。查看系统日志(如
/var/log/messages、dmesg)是否有OOM相关记录,同时监控任务运行时的资源占用情况。 - Writer代码优化点:
- 每次
write调用都重新创建JdbcTemplate会额外消耗资源,建议通过依赖注入方式注入JdbcTemplate,而非每次循环实例化。 - 循环中每个对象单独执行三次数据库操作,无批量处理,导致大量交互拖慢速度,增加超时风险。建议使用
batchUpdate合并批量操作。 - 缺乏异常捕获机制,若某条记录处理失败可能静默抛出异常但未被日志记录,可在循环中添加try-catch块记录详细异常信息。
- 每次
内容的提问来源于stack exchange,提问作者Saimuga
相关产品推荐
相关产品推荐

