Spring Batch : JobExecutionAlreadyRunningException: A job execution for this job is already running

스프링 배치가 운영되고 있는 서버가 예상치 못한 종료를 하게 되면 다음번 실행에 아래와 같은 예외 코드가 떨어지게 됩니다.
application.log.2020-03-17.0.log:Caused by: org.springframework.batch.core.repository.JobExecutionAlreadyRunningException: A job execution for this job is already running: JobInstance: id=3, version=0, Job=[archiveOldChatsJob]
잡이 시작된 시점에 메타 테이블에 STARTED 를 기록 했지만, 서버가 비정상 종료 됨으로서 결과를 기록 하지 못해서 발생 하는 현상으로 보여지는데,
애초에 서버의 비정상 종료가 일어나면 안되는것이고, 일어나더라도 자동적으로 복구가 되기를 바라지만, 그 훌륭한 스프링도 배치쪽은 그렇게 많이 신경을 쓰지 않는것 같네요.
우선, 일어난 문제 현상은 해결을 해야 하는데, 좀 찾아보면 몇가지 해결방안이 보입니다.
제가 선택한 방법은 메타정보가 저장되는 디비 테이블을 수동으로 업데이트 하는것입니다.
 UPDATE BATCH_JOB_EXECUTION SET END_TIME = SYSTIMESTAMP, STATUS = 'FAILED', EXIT_CODE = 'COMPLETED' WHERE JOB_EXECUTION_ID = (SELECT MAX(JOB_EXECUTION_ID) FROM BATCH_JOB_EXECUTION WHERE JOB_INSTANCE_ID = #{jobInstanceId} ); 
문제가 반복적으로 재현되거나, 서버 구조상 해결 될 수 없는 경우에는 ContextRefreshEvent 를 수신하는 ApplicationListner 를 구현해서 매 시작 마다 업데이트를 하는 방법도 있는것 같습니다.
@Component public class ContextRefreshEventListener implements ApplicationListener<ContextRefreshedEvent> { private static final Logger LOGGER = LoggerFactory.getLogger(BatchJobRestarter.class); @Autowired private JobExplorer jobExplorer; @Autowired JobRepository jobRepository; @Autowired JobOperator jobOperator; @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { LOGGER.info("Container restart: restarting 'running' batch jobs"); List<String> jobs = jobExplorer.getJobNames(); for (String job : jobs) { Set<JobExecution> runningJobs = jobExplorer.findRunningJobExecutions(job); for (JobExecution runningJob : runningJobs) { try { LOGGER.info("Restarting job {} with parameters {}", runningJob.getJobInstance().getJobName(), runningJob.getJobParameters().toString()); runningJob.setStatus(BatchStatus.FAILED); runningJob.setEndTime(new Date()); jobRepository.update(runningJob); jobOperator.restart(runningJob.getId()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } } } }

Comments

  1. 저도 겪은 황당한 문제입니다.
    스프링 배치의 전체적인 구조는 만족스러운데 이렇게 부실하다니 실망이네요.
    아주 당연하게 시작시 자동 복구가 될 줄 알았는데 클러스터링 환경을 고려 한 것인지 제대로 동작이 안되네요

    ReplyDelete

Post a Comment

Popular posts from this blog

3.1.0 릴리즈 알림

문자미러링 기능 출시 완료