본문 바로가기

카테고리 없음

Springboot Schedule - @EnableScheduling, @Scheduled, abstract, 동적주기

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

스프링에서 제공하는 Schedule 기능을 사용했었는데, 정리하는 차원으로 남깁니다. 

 

1. @EnableScheduling 을 이용한 Schedule 설정

  -. 설정파일에 스케쥴을 사용하겠다는 의미로 @EnableScheduling을 추가하여 스케쥴링 기능을 사용하겠다는 것을 표기하여 줄 수 있다.

  -. @Scheduled 어노테이션을 메서드 상단에 붙여 메서드가 주기적으로 동작하도록 설정할 수 있다.

 

단점 : Scheduler 자체의 동작여부를 직접정의할 필요가 있을 경우 스케쥴러의 동작을 제어할 수 없다. 

@Component
@EnableScheduling
@PropertySource(name = "classpath:/constants.yml", value = "")
public abstract class ScheduledConfig {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("prefix.schedule.thread-pool")
    private String THREAD_PREFIX_NAME;

    @Bean
    public TaskScheduler scheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix(THREAD_PREFIX_NAME);
        scheduler.setPoolSize(Runtime.getRuntime().availableProcessors() * 2);
        return scheduler;
        }
}
--------------------------------------------------------------------------------------------

@Component
@EnableScheduling
public class LotteryCrawling {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private final String scheduleTerm = "0/5 * * * * *";

    /*  아래 표현식으로 다양하게 주기를 설정할 수 있다. 
        cron : cron 표현식을 사용하여 특정 시간마다 동작 ("초 분 시 일 월 요일" 6필드)
        fixedDelay : 작업이 끝난 시점 기준, milliseconds 마다 동작
        fixedDelayString : fixedDelay와 동일, 속성값만 String으로 입력
        fixedRate : 작업이 시작한 시점 기준, milliseconds 마다 동작
        fixedRateString : fixedRate와 동일, 속성값만 String으로 입력
        initialDelay : 최초 수행 지연 시간, milliseconds 이후에 실행
        initialDelayString : initialDelay와 동일, 속성값만 String으로 입력
        zone : 시간대, Oracle Real-Time Collabaration에서 지원하는 시간대 목록
        설정하지 않으면 default는 설치된 서버의 시간대로 설정됨
        시간대를 직접 설정해야 할 경우에는 아래 오라클 문서를 참고하시면 되요. (예시: "Asia/Seoul")
        https://docs.oracle.com/cd/B13866_04/webconf.904/b10877/timezone.htm

        * : 모든 값
        ? : 설정 없음 (일과 요일만 사용 가능)
        , : 배열 ex) 1,5,8 : 1,5,8에만
        - : 앞부터 뒤까지 ex) 1-3 : 1부터 3까지
        / : 앞부터 뒤마다 ex) 1/3 : 1부터 매3마다 1,4,7,11...
    */

    @Scheduled(cron = scheduleTerm)
    // 필요에 따라서는 아래와 같이 SpEL을 사용하여 프로퍼티의 값에 따른 주기적인 작업설정도 가능하다.
    //@Scheduled(cron="${properties value}")

    public void getCrawlingData() {
        // to do somthing

        }
}

2. Dynamic Scheduling

  -. ThreadPoolTaskScheduler라는 클래스를 활용하여 추상클래스로 동작시점을 직접정의

 

다양하게 정의하여 사용하기 위해서 실행영역과 주기설정을 추상클래스로 정의하도록 구현하였다.

그리고 부트 실행과 동시에 스케줄이 등록될 수 있도록 ApplicationRunner를 이용하여 초기 실행하였다. 

public abstract class DynamicScheduledConfig {

    private Logger logger = LoggerFactory.getLogger(getClass());
    private ThreadPoolTaskScheduler scheduler;

    public void stopScheduler() {
        if(scheduler != null) {
            scheduler.shutdown();
        }
    }

    public void startScheduler() {
        scheduler = new ThreadPoolTaskScheduler();
        scheduler.initialize();
        scheduler.setPoolSize(4);
        scheduler.schedule(getRunnable(), getTrigger());
    }

    private Runnable getRunnable() {
        return new Runnable() {
            @Override
            public void run() {               
                runner();
             }
        };
    }

    public abstract void runner();
    public abstract Trigger getTrigger();
}
--------------------------------------------------------------------------------------------
@Component
public class ScheduleApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        DynamicScheduledConfig scheduledConfig = new DynamicScheduledConfig() {
            @Override
            public void runner() {
                //to do something
            }

            @Override
            public Trigger getTrigger() {
                return new CronTrigger("0/10 * * * * *");
            }
        };

        scheduledConfig.startScheduler();
    }
}

참고) www.daleseo.com/spring-boot-runners/
스프링 부트 애플리케이션 구동 시점에 특정 코드 실행 시키기기 위해서 2가지 인터페이스를 제공

1. CommandLineRunner

  -. 인터페이스는 구동 시점에 실행되는 코드가 자바 문자열 아규먼트 배열에 접근해야할 필요가 있는 경우에 사용

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class DemoCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner Args: " + Arrays.toString(args));
    }
}

2. ApplicationRunner

  -. CommandLineRunner 인터페이스와 마찬가지로 구동 시점에 run() 메소드를 실행시키지만 다른 타입의 인자를 받음.

    단순 인자의 스트링 배열을 포함한 추상화한 ApplicationArguments 타입의 객체가 대신 run() 메소드의 인자로 넘어옴

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class DemoApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner Args: " + Arrays.toString(args.getSourceArgs()));
    }
}