繁体   English   中英

Spring 批量长时间运行tasklet数据库超时

[英]Spring batch long running tasklet database timeout

鉴于我的工作流作业有这个 Spring 批处理配置,并且我正在为我的 spring 批处理表使用 Sql 服务器数据库:

public class MyConfiguration extends AbstractConfiguration {
   
    @Bean
    @Qualifier("pollStep")
    public Step pollStep() {
        return stepBuilderFactory.get("pollStep")
                                 .tasklet(filePollingTasklet())
                                 .listener(promoteContextListener())
                                 .build();
    }

    @Bean
    @StepScope
    private Tasklet filePollingTasklet() {
        return ((stepContribution, chunkContext) -> getStatus(stepContribution, chunkContext));
    }

    private RepeatStatus getStatus(StepContribution stepContribution, ChunkContext chunkContext) {
        //some code
        Map<String, Boolean> result = poller.pollForFile(myContext, sourceInfo);
        return RepeatStatus.FINISHED;
    }

}

我的应用程序轮询远程服务器上的文件。 100 分钟后,当它找不到文件时poller.pollForFile()抛出运行时异常,我的步骤状态为 UNKNOWN 并且应用程序退出并出现异常:

c.m.s.j.SQLServerException: Connection reset at 
c.m.s.j.SQLServerConnection.terminate(SQLServerConnection.java:1667) at 
c.m.s.j.SQLServerConnection.terminate(SQLServerConnection.java:1654) at 
c.m.s.j.TDSChannel.write(IOBuffer.java:1805) at c.m.s.jdbc.TDSWriter.flush(IOBuffer.java:3581) at 
c.m.s.jdbc.TDSWriter.writePacket(IOBuffer.java:3482) at 
c.m.s.jdbc.TDSWriter.endMessage(IOBuffer.java:3062) at 
c.m.s.j.TDSCommand.startResponse(IOBuffer.java:6120) at 
c.m.s.j.TDSCommand.startResponse(IOBuffer.java:6106) at 
c.m.s.j.SQLServerConnection$1ConnectionCommand.doExecute(SQLServerConnection.java:1756) at 
c.m.s.j.TDSCommand.execute(IOBuffer.java:5696) at 
c.m.s.j.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) at 
c.m.s.j.SQLServerConnection.connectionCommand(SQLServerConnection.java:1761) at 
c.m.s.j.SQLServerConnection.rollback(SQLServerConnection.java:1964) at 
c.z.h.p.ProxyConnection.rollback(ProxyConnection.java:375) at 
c.z.h.p.HikariProxyConnection.rollback(HikariProxyConnection.java) at 
o.h.r.j.i.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:116) ... 50 common frames omitted Wrapped by: u003c#7f0e356au003e o.h.TransactionException: Unable to rollback against JDBC Connection at ...

我认为 sql 服务器数据库连接已超时并关闭,并且 spring 批处理无法执行回滚和数据库更新。 理想情况下,我希望状态为 FAILED,即当我使用 H2 在本地运行时,但在这种情况下,我可以使用什么策略或技术来克服这个问题? 退出消息没有pollForFile()抛出的异常错误,而是org.springframework.transaction.TransactionSystemException: Could not roll back JPA transaction; nested exception is org.hibernate.TransactionException: Unable to rollback against JDBC Connectionat org.springframework.transaction.TransactionSystemException: Could not roll back JPA transaction; nested exception is org.hibernate.TransactionException: Unable to rollback against JDBC Connectionat

有没有办法解决这个问题? 如果我要从 tasklet 转移到面向块并在 ItemReader 的read()方法中执行轮询逻辑怎么办?

你的想法是正确的。 当提交失败时,Spring Batch 无法正确更新以UNKNOWN而不是FAILED结尾的步骤状态。 这里有一个未解决的问题: https://github.com/spring-projects/spring-batch/issues/1826 虽然您的例外不同,但问题是相同的。 我试图在这里解决这个问题: https://github.com/spring-projects/spring-batch/pull/591但我决定放弃它(您可以在该 PR 中找到有关原因的更多详细信息)。

要解决此问题,您需要确保在 tasklet 中处理任何(运行时)异常(或在面向块的步骤的情况下在项目编写器中处理)。 在您的情况下,您可以增加事务的超时并在 tasklet 中捕获运行时异常(您可以将其包装在一个有意义的异常中,您可以从 tasklet 重新抛出该异常以使其失败)。

编辑:添加增加事务超时的示例

@Bean
@Qualifier("pollStep")
public Step pollStep() {
   DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
   attribute.setTimeout(60 * 100);
   // set other transaction attributes
   return stepBuilderFactory.get("pollStep")
                            .tasklet(filePollingTasklet())
                            .transactionAttribute(attribute)
                            .listener(promoteContextListener())
                            .build();
}



暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM