Spring famework 사용 시 멀티서버 즉, 2개 이상의 서버로 구성된 환경에서
스프링 스케줄러를 사용하게 되면 중복된 cron 이 실행된다.
이는 cron 작업이 was마다 실행되기 때문에 발생하는 문제로
was 개수만큼 중복된 cron 이 실행되어 한 번만 실행되는 것이 아닌 두번 이상 실행이 되는 것이다.
서버를 삭제 후 재 생성하기도 했지만 결국 스프링 스케줄러 중복실행 문제는 해결하지 못했고,
2개 이상의 서버에서 중복실행을 막기위해서 Lock기능을 이용하여 DB를 공통참조하도록 제공하는
라이브러리(Lock API)인 ShedLock 를 통해 해결할 수 있었다.
처리방식은 ShedLock 테이블에 동일한 데이터가 있는지 여부를 파악한 후,
만약 동일한 이름의 데이터가 있다면 Scheduling 을 중단하고
동일한 데이터가 없다면 ShedLock 테이블에 이름, 잠금일시, 기간 등을 설정하여 insert 해준다.
처리방법은 다음과 같다.
1. Oracle DB
Lock 기능을 사용하기 위해서 DB 에 테이블을 생성한다.
create table SHEDLOCK (
name varchar (64),
LOCK_UNTIL timestamp (3) null ,
LOCKED_AT timestamp (3) null ,
LOCKED_BY varchar (255),
primary key (name)
);
2. pom.xml
pom.xml 에 라이브러리를 추가한다.
<!-- === Scheduler lock === -->
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>3.0.0</version>
</dependency>
<!-- JDBC Template -->
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>3.0.0</version>
</dependency>
3. root-context.xml
myBatis(JDBC)설정한 곳 아래에 Bean 을 등록해준다.
※ Controller 에서 @Bean 을 등록해주어도 된다.
<bean id="lockProvider" class="net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider">
<constructor-arg ref="dataSource"/>
</bean>
4. Service 단
본인은 Controller 에서는 특정 URL 사이트로 연결하도록 잡아주기만 하고,
Service 단에서는 cron 작업(특정날짜 및 시각 설정)을 해주었다.
따라서 Service 단에서 클래스와 메소드에 아래와 같이 어노테이션을 추가해준다.
@EnableScheduling @EnableSchedulerLock(defaultLockAtMostFor = "PT30S") private static final String ONE_MIN = "PT1M"; // 1분동안 LOCK @SchedulerLock(name = "고유한 이름 지정", lockAtMostForString = ONE_MIN, lockAtLeastForString = ONE_MIN) |
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S") // Scheduler Lock 사용 가능 설정 (기본 30초동안 Lock)
@Service
public class ScheduleService implements InterScheduleService {
private static final String ONE_MIN = "PT1M"; // 1분동안 Lock
@Scheduled(cron="0 30 4 1 1 *") // 매년 1월 1일 4시 30분
@SchedulerLock(name = "runWorkTime", lockAtMostForString = ONE_MIN, lockAtLeastForString = ONE_MIN)
public void getWorking() throws Exception {
//do something....
}
※ 이 글은 아래의 블로그 글을 참고하였습니다.
https://steady-snail.tistory.com/174
'Langauge > Spring framework' 카테고리의 다른 글
[Spring] 스프링 오류 (22) - 500번 에러 처리(에러이미지 표시) (0) | 2022.11.09 |
---|---|
[Oracle 오류] 오라클 및 크롬 웹브라우저 무한로딩 해결방법 (오라클 완전 제거하기 + 데이터베이스 복구) (0) | 2022.10.22 |