본문 바로가기

Backend Development/Spring boot

[Spring Boot] Quartz 배치 DisallowConcurrentExecution 설정

Spring boot에서 Quartz를 활용하여 배치를 수행시킬때 예기치 못하게 처리 데이터가 많아져서 배치 주기 안에 Job을 못끝내는 경우가 발생할 수 있다.

 

수행중인 Batch job이 끝나지 않았다면 다음 Trigger 주기때 Job은 실행이 되는 것일까? 그렇다면 실행중에 또 실행이 되어서 결과값에 영향을 주지 않을까?

 

배치 주기 5초인 Job이 10초간 실행될때 테스트

 

아래와 같이 5초 간격으로 도는 Test Job을 등록을 해두었다 해당 잡은 5초마다 log 테이블에 start시간과 end time을 저장한다.

 

 

Job의 내용은 아래와 같이 간단하다. 수행되자마자 DB에 start 시간을 기록하고 10초간의 Sleep 시간을 갖고 마지막에 end 시간을 저장하고 종료된다. 즉 주기 5초보다 Job실행이 10초로 긴 상황이다.

    @Override
    public void processTestExecution(JobExecutionContext context) {
        String startDatetime = DateUtil.getNowStringWithFormat(DATEFORMAT_yyyyMMddHHmmss);

        batchService.insertBatchLog(context, BatchLog.builder()
                .startDatetime(DateUtil.getNowStringWithFormat(DATEFORMAT_yyyyMMddHHmmss)).statusCode(EXECUTE).build());

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        batchService.insertBatchLog(context, BatchLog.builder()
                .startDatetime(startDatetime).endDatetime(DateUtil.getNowStringWithFormat(DATEFORMAT_yyyyMMddHHmmss)).statusCode(SUCCESS).build());
    }

 

 

Job을 어느정도 실행시키고 DB 로그 테이블을 확인해 보면 start job이 종료가 되지 않았는데도 다음번 Job이 실행이 되어서 DB 로그가 5초간격으로 계속 쌓이고 있는 것을 볼 수 있다. 이는 batch 잡이 지연이 되어서 주기 안에 못 끝나면 실행 도중에 주기에 맞춰 Job이 또 실행이 된다는 의미이다.

 

주기를 예측해서 넉넉히 잡아두면 문제가 안되겠지만 처리할 데이터 양이 일별로 편차가 있거나 예측이 불가능하다면 중복실행으로 인한 문제가 발생 할 수도 있다. 이런 경우에는 Spring quarts 의 어노테이션으로 중복 실행을 막을 수 있다.

 

@DisallowConcurrentExecution 어노테이슨 Job에 추가

 

Spring Quartz 라이브러리에서는 @DisallowConcurrentExecution 어노테이션을 붙여서 Job 수행 도중에 Job이 병렬적으로 또 실행되는것을 막아주는 기능이 있다.

 

사용법은 간단하다 QuartzJobBean을 상속한 Job Class에 아래와 같이 어노테이션을 붙여주면 된다.

@DisallowConcurrentExecution
public class TestJob extends QuartzJobBean {

    @Autowired
    private ITestService testService;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        testService.processTestExecution(context);
    }
}

 

 

위와 같이 어노테이션 작업 후 Job 수행 변화를 보자.

Job 수행 시간 (end_dtm - start_dtm)이 10초 가량으로 늘어나 있고 Job 로그도 5초간격으로 꼬박꼬박 안들어가져 있따. 즉 10초간의 잡 수행이 종료되고 다음 Job이 수행됨을 볼 수 있다.

 

-- The End --