티스토리 뷰

반응형

Spring Batch 에서 자주 사용하는 @Scheduled 어노테이션이 있습니다.  이는 Spring Boot 기반에서 제공이 되기 때문에 배치와 같이 잡 스케줄러에서 주로 사용하기도 합니다. 시간이 되면 알아서 작동되는 서비스기능이지만 여기에는 단점이 하나 존재합니다. 바로 같은 서비스를 동시에 돌릴수는 없다는 점입니다. 즉, 중복 실행 방지 옵션이 있습니다.

보통 Schedule가 붙고 Batch를 실행하게 되면 Batch Job Repository를 수행하는 Meta Table들이 많이 생깁니다. 그 메타 테이블들은 제가 작성한 다른 글에 좀 더 상세하게 기록되어 있습니다.

https://abbo.tistory.com/255

 

Spring Batch Job Repository

Job Repository는 스프링 배치에 대한 메타 데이터를 저장합니다. 그 구조는 spring-batch-core에 존재합니다. mysql을 사용하므로 mysql.sql을 복사해 생성해보겠습니다. 다음과 같이 여러 테이블이 생성되

abbo.tistory.com

 

Batch를 사용하면 이 테이블들을 참고하여 수행이 되게 되지만, 만일 1번 서버와 2번 서버가 존재하여 같은 스케줄을 동작시키게 되면 메타 테이블의 영향을 받아 수행중이라는 플래그를 인지한다음 2번째로 수행시킨 스케줄에 관해 서비스 도중 에러가 발생하지 않아도 Fail 이 떨어집니다. 왜냐하면 @Scheduled 안에서 같은 스케줄을 작동시켰을 때 다른 스케줄의 작동을 무시한다라는 기본값을 가지고 있기 때문입니다. 

 

그래서 이런 점을 개선하고 다른 서버(또는 다른 노드)에서도 같은 서비스를 수행가능하도록 하는 플러그인인 SchedLock 라이브러리를 사용하여 개발하는 방법이 있다고 합니다. 


build.gradle

dependencies {
    implementation("net.javacrumbs.shedlock:shedlock-spring:4.33.0")
}

application.yml

shedlock:
   table: shedlock

 

SchedulerConfig.java

@EnableScheduling 을 사용하기 위한 클래스를 작성하여 @Scheduled 와 관련된 어노테이션에 설정을 진행합니다.

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "10s")
public class SchedulerConfig {
    
    @Bean
    public LockProvider lockProvider(DataSource ds) {
        return new JdbcTemplateLockProvider(
            JdbcTemplateLockProvider.Configuration.builder()
                .withJdbcTemplate(new JdbcTemplate(ds))
                .usingDbTime() // Database의 기본 타임셋을 사용합니다.
                .build()
            );
    }
}

 

AbboSchedule.java

이제 위에서 설정한 @SchedulerLock 을 사용하여 클래스에 적용해보겠습니다.

@Component
@RequriedArgsConstructor
public AbboScheudle {

    private final AbboScheduleBatch abboScheduleBatch;

    @Scheduled(cron = "1 2 3 * * *") // 매일 3시 2분 1초
    @SchedulerLock(name = "abboSchedule1", lockAtLeastFor = "30s", lockAtMostFor = "30s")
    public void abboSchedule1() {
       abboScheduleBatch.run();
    }
}

이제 이렇게 수행을 했을 경우 들어가는 @SchedulerLock 어노테이션에 붙는 옵션은 아래에 설명해두겠습니다.

  • name: 스케줄러에 락을 거는데 구분하는 키값
  • lockAtLeastFor: 실질적으로 락이 걸리는 최소 보장된 시간값
  • lockAtMostFor: 해당 스케줄러 노드가 다운될때 락 보장시간 Limit 값
  • lockAtLeaftFor > lockAtMostFor 로 시간을 잡으면 에러 발생, lockAtMostFor 시간이 수행시간보다 짧게 잡히는 경우 락을 해제하게 되므로 서비스 수행시간보다 길게 잡기

 


저는 이번 글에서 아래의 글들을 참고하여 작성하고 개발에 적용시켜보았습니다.

https://github.com/lukas-krecan/ShedLock

 

GitHub - lukas-krecan/ShedLock: Distributed lock for your scheduled tasks

Distributed lock for your scheduled tasks. Contribute to lukas-krecan/ShedLock development by creating an account on GitHub.

github.com

https://jsonobject.tistory.com/601

 

Spring Boot, ShedLock, 멀티 노드 환경에서 특정 스케쥴 작업의 중복 실행 방지하기

개요 Spring Boot에서 특정 빈의 메써드에 지정된 @Scheduled 는 특정 시간 또는 주기로 애플리케이션 로직이 실행될 수 있도록 해준다. @Scheduled에서 발생할 수 있는 주요 이슈로, 분산 시스템의 개념

jsonobject.tistory.com

 

반응형
댓글
공지사항