Schedule의 사전적 정의는 "일정[시간 계획]을 잡다"라는 뜻입니다.
Spring Boot를 통해 Spring에서 지원하는 스케줄러를 간편하게 작성할 수 있습니다.
Schedule 기능 켜기
자바 설정(Java configuration) 관련 클래스에 @EnableScheduling를 추가하면 스케쥴링 기능을 사용할 수 있습니다.
@EnableScheduling
@SpringBootApplication
public class SchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
}
구현하기
@Scheduled 어노테이션을 메소드에 선언하며 작업을 실행이 가능하며, 실행 주기는 cron, fixedDelay, fixedRate 라는 세 개의 속성으로 지정할 수 있습니다.
cron으로 실행 주기 설정하기
그 전에 crontab 주기 설정 방법부터 알아보겠습니다.
* * * * * *
초(0-59) 분(0-59) 시간(0-23) 일(1-31) 월(1-12) 요일(0-7)
각 별 위치에 따라 주기를 다르게 설정 할 수 있습니다.
순서대로 초-분-시간-일-월-요일 순이다. 그리고 괄호 안의 숫자 범위 내로 별 대신 입력 할 수 있습니다.
요일에서 0과 7은 일요일이고, 1부터 월요일이고 6이 토요일입니다.
1분마다 특정 작업이 실행되도록 스케줄을 설정합니다. 1분마다 호출되고, 이 시간은 이전 호출이 완료된 시점부터 계산됩니다.
@Scheduled(cron = "1 * * * * ?")
public void cronJobSch() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
String strDate = sdf.format(now);
System.out.println("작업 날짜 시간:: " + strDate);
}
fixedDelay로 실행 주기 설정하기
다음 예제도 1초마다 호출되고, 이 시간은 이전 호출이 완료된 시점부터 계산됩니다.
@Scheduled(fixedDelay = 1000)
public void scheduleFixedDelayTask() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
String strDate = sdf.format(now);
System.out.println("작업 날짜 시간 fixedDelay:: " + strDate);
}
fixedRate로 실행 주기 설정하기
고정된 비율로 실행하기를 원한다면 fixedRate를 사용하면 됩니다.
다음 예제는 각 호출의 연속적인 시작 시각의 간격으로 계산된 1초마다 실행됩니다.
@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTask() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
String strDate = sdf.format(now);
System.out.println("작업 날짜 시간 fixedRate::" + strDate);
}
fixedDelay와 fixedRate의 delay 하기 시작하는 시점입니다.
fixedDelay는 이전 수행이 종료된 시점부터 delay후에 재호출 되고, fixedRate는 이전 수행이 시작된 시점부터 delay후에 재호출 됩니다. 그러므로 fixedRate로 지정 시 작업이 동시에 여러 개가 돌 가능성이 존재합니다.
Thread pool 설정
기본적으로 모든 @Scheduled 작업은 Spring에 의해 생성된 한 개의 스레드 풀에서 실행됩니다.
실제로 로그를 보면 같은 쓰레드로 확인될 것이다.
System.out.println("현재 쓰레드 : "+ Thread.currentThread().getName());
결과
현재 쓰레드 : scheduling-1
문제 상황
한 개의 스레드 풀에서 실행되기 때문에 하나의 Scheduled이 돌고 있다면 그것이 다 끝나야 다음 Scheduled이 실행되는 문제가 있습니다.
다음 예시에서 우리는 1초마다 실행 되기를 바랐지만, 3초나 걸리는 작업이 있기 때문에 1초마다 작업이 실행이 안 되는 것을 알 수 있습니다.
@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTask() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date now = new Date();
String strDate = sdf.format(now);
System.out.println("작업 날짜 시간 fixedRate::" + strDate);
System.out.println("현재 쓰레드 : "+ Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
스케쥴링 설정 클래스를 사용한 쓰레드 풀 설정
스프링 부트에서 설정을 통해 Schedule에 대한 쓰래드 풀을 생성하고 그 쓰레드 풀을 사용하여 모든 스케줄 된 작업을 실행하도록 할 수 있습니다.
아래는 스레드 풀 사이즈를 10개로 설정한 예시입니다.
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
private final int POOL_SIZE = 10;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool");
threadPoolTaskScheduler.initialize();
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
스케줄이 돌고있는 메서드에서 현재 쓰레드의 이름을 로깅하면 아래와 같은 출력이 표시됩니다.
소스코드 보기
https://github.com/keepseung/SpringBoot-Blog-Source/tree/main/scheduler
'스프링 > Spring' 카테고리의 다른 글
[SpringBoot] 서블릿의 HttpSession을 사용해 세션 구현하기 (0) | 2021.10.26 |
---|---|
[SpringBoot] 스프링부트에서 비동기 처리하기 (0) | 2021.10.25 |
Rabbitmq + SpringBoot 샘플 프로젝트 만들기 (0) | 2021.10.16 |
RabbitMQ 설치하기 (0) | 2021.10.16 |
Spring Boot 프로젝트 생성하기 (0) | 2021.01.07 |