停止弹出批处理JobExecution停止步骤,但作业本身停留在“停止”状态

时间:2012-02-13 13:04:06

标签: java mysql spring spring-batch

我有一个简单的工作设置:

<job id="myJob" restartable="false"
         xmlns="http://www.springframework.org/schema/batch"
         job-repository="dbJobRepository">
        <step id="myStep">
            <tasklet>
                <chunk reader="myReader"
                       processor="myProcessor"
                       writer="myWriter"
                       commit-interval="100">
                </chunk>
            </tasklet>
        </step>
</job>

<bean id="dbJobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
        <property name="databaseType" value="mysql" />
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager"/>
        <property name="isolationLevelForCreate" value="ISOLATION_DEFAULT"/>
</bean>

通过Quartz容器进程触发作业:

public void runHook() throws Exception {
    ...
    this.jobParameters = jobParamsBuilder.toJobParameters();
    JobExecution jobExecution = jobLauncher.run(this.job, this.jobParameters);
    BatchStatus batchStatus = jobExecution.getStatus();
    ...
}

public void abort() {
    ...
    JobOperator jobOperator = KBeansProvider.getBean("jobOperator");
    JobRepository jobRepository = KBeansProvider.getBean("dbJobRepository");
    JobExecution jobExecution = jobRepository.getLastJobExecution(this.jobBeanId,this.jobParameters);

    try {
        jobExecution.stop();
        jobOperator.stop(jobExecution.getJobId());
    ...
}

在调用abort()时,找到执行并且步骤本身以秒的方式停止:

2012-02-13 13:59:37,566 INFO [org.springframework.batch.core.repository.support.SimpleJobRepository] - <Parent JobExecution is stopped, so passing message on to StepExecution>
2012-02-13 13:59:37,569 INFO [org.springframework.batch.core.step.ThreadStepInterruptionPolicy] - <Step interrupted through StepExecution>
2012-02-13 13:59:37,573 ERROR [org.springframework.batch.core.step.AbstractStep] - <Encountered an error executing the step>
org.springframework.batch.core.JobInterruptedException: Job interrupted status detected.
    at org.springframework.batch.core.step.ThreadStepInterruptionPolicy.checkInterrupted(ThreadStepInterruptionPolicy.java:42)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:277)

如预期的那样,batch_step_execution表中的步骤状态设置为STOPPED。 问题是runHook方法被阻止: JobExecution jobExecution = jobLauncher.run(this.job,this.jobParameters); (由于系统限制,我必须在这里使用同步的jobLauncher) 并且该作业的batch_job_execution条目位于&#39; STOPPING&#39;状态。

需要注意的一个奇怪的行为是,有时状态会更改为STOPPED并且jobLauncher.run()将返回,但仅在相当长的时间后,最少10分钟,最多一个小时或两个小时。

这是runHook()线程的堆栈跟踪:

MyClusteredReadyScheduler_Worker-3@8362, prio=3, in group 'main', status: 'RUNNING'
      at java.net.SocketInputStream.socketRead0(SocketInputStream.java:-1)
      at java.net.SocketInputStream.read(SocketInputStream.java:129)
      at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:113)
      at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:160)
      at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:188)
      at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2499)
      at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3010)
      at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2943)
      at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3486)
      at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:919)
      at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1416)
      at com.mysql.jdbc.RowDataDynamic.nextRecord(RowDataDynamic.java:416)
      at com.mysql.jdbc.RowDataDynamic.next(RowDataDynamic.java:395)
      at com.mysql.jdbc.RowDataDynamic.close(RowDataDynamic.java:173)
      at com.mysql.jdbc.ResultSetImpl.realClose(ResultSetImpl.java:7623)
      at com.mysql.jdbc.ResultSetImpl.close(ResultSetImpl.java:907)
      at org.apache.tomcat.dbcp.dbcp.DelegatingResultSet.close(DelegatingResultSet.java:152)
      at org.springframework.jdbc.support.JdbcUtils.closeResultSet(JdbcUtils.java:107)
      at org.springframework.batch.item.database.AbstractCursorItemReader.doClose(AbstractCursorItemReader.java:375)
      at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.close(AbstractItemCountingItemStreamItemReader.java:124)
      at org.springframework.batch.item.support.CompositeItemStream.close(CompositeItemStream.java:83)
      at org.springframework.batch.core.step.tasklet.TaskletStep.close(TaskletStep.java:297)
      at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:255)
      at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
      at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
      at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
      at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
      at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
      at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
      at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
      at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
      at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48)
      at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:114)

查看堆栈跟踪,看起来故障与jdbc连接有某种关系, 所以我会提供一些可能有用的额外信息。

我的读者扩展了AbstractCursorItemReader,相关方法包括:

    @Override
        public void afterPropertiesSet() throws Exception {
            setSql(this.sql);
            this.setSaveState(false);
            this.setVerifyCursorPosition(false);
            this.setIgnoreWarnings(true);
            this.setUseSharedExtendedConnection(false);
            this.setQueryTimeout(10000);
    }

    protected void cleanupOnClose() throws Exception {
                JdbcUtils.closeStatement(this.preparedStatement);
    }

    protected void openCursor(Connection con) {
                try {
                    if (isUseSharedExtendedConnection()) {
                        preparedStatement = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
                                ResultSet.HOLD_CURSORS_OVER_COMMIT);
                    }
                    else {
                        preparedStatement = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
                    }

                    applyStatementSettings(preparedStatement);
                    if (this.preparedStatementSetter != null) {
                        preparedStatementSetter.setValues(preparedStatement);                           
                    }
                    preparedStatement.setFetchSize(Integer.MIN_VALUE);

                    this.rs = preparedStatement.executeQuery();
                    ProcessLogger.getLogger().debug("Executed query: " + this.rs.getStatement());
                }
}

我所希望的行为是让工作立即停止 - 或者至少在步骤停止后不久停止。

0 个答案:

没有答案