티스토리 뷰
Spring Batch 에서 자주 사용하는 @Scheduled 어노테이션이 있습니다. 이는 Spring Boot 기반에서 제공이 되기 때문에 배치와 같이 잡 스케줄러에서 주로 사용하기도 합니다. 시간이 되면 알아서 작동되는 서비스기능이지만 여기에는 단점이 하나 존재합니다. 바로 같은 서비스를 동시에 돌릴수는 없다는 점입니다. 즉, 중복 실행 방지 옵션이 있습니다.
보통 Schedule가 붙고 Batch를 실행하게 되면 Batch Job Repository를 수행하는 Meta Table들이 많이 생깁니다. 그 메타 테이블들은 제가 작성한 다른 글에 좀 더 상세하게 기록되어 있습니다.
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
https://jsonobject.tistory.com/601
'Server' 카테고리의 다른 글
DataGrip Mysqldump 사용방법 (5) | 2022.08.18 |
---|---|
LetsEncrypt SSL 인증서 갱신/삭제방법 및 자동갱신 적용하기 (0) | 2022.08.17 |
Docker Compose 사용법 (2) | 2022.08.16 |
[Java] JPA 에서 group 을 컬럼명으로 쓰는 방법 (0) | 2022.08.12 |
Jenkins에서 배치 생성하기 (1) | 2022.08.01 |
[Java] JPA Boolean/LocalDate Soft Delete 구현하기 (1) | 2022.06.20 |