본문 바로가기
프레임워크/스프링

Spring Scheduler와 Spring Quartz 차이

by so5663 2024. 4. 13.

스케줄러러를 사용할 일이 있었는데 찾아 보니까

Spring에서 Spring Scheduler와 Spring Quartz라는 2가지 방식으로 제공됩니다.

 

Spring Scheduler

제가 프로젝트에서 채택했던 방식입니다. 

사용법이 쉽고 Spring Boot starter에서 지원하기 때문에 따로 의존성을 추가 하지 않고

어노테이션만 추가하면 사용할수 있습니다.

 

ScheduledConfig.java

 
@Configuration
@EnableAsync
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler threadPool = new ThreadPoolTaskScheduler();

        int n = Runtime.getRuntime().availableProcessors();
        threadPool.setPoolSize(n);
        threadPool.initialize();

        taskRegistrar.setTaskScheduler(threadPool);
    }

    @Bean
    public LockProvider lockProvider(DataSource dataSource) {
        return new JdbcTemplateLockProvider(dataSource);
    }
}

 

lockProvider 메서드는 LockProvider를 빈으로 등록하고 데이터베이스를 사용하여 락(lock)을 관리하는 JdbcTemplateLockProvider를 생성했습니다.

락은 다중 스레드 환경에서 데이터 일관성을 보장하기 위해 사용했습니다.

 

@Component
@RequiredArgsConstructor
@EnableSchedulerLock(defaultLockAtMostFor = "PT60S")
public class GradeScheduler {

    private final GradeService gradeService;

    @Async
    @Scheduled(cron = "0 0 5 1 * *")
    @SchedulerLock(name = "Update_User_Grade", lockAtLeastFor = "PT10S")
    public void updateUserGradeScheduler() {
        gradeService.updateUserGrade();
    }
}

 

@EnableSchedulerLock(defaultLockAtMostFor = "PT60S"): 이 어노테이션은 spring-task-scheduler-lock 라이브러리에서 제공하는 기능으로, 스케줄러 락(lock)을 활성화합니다. defaultLockAtMostFor 속성은 기본적으로 설정된 락의 최대 유지 시간을 나타냅니다. 여기서는 60초로 설정되어 있으므로, 스케줄러에 의해 실행되는 작업은 최대 60초 동안 락을 유지합니다.

 

@Async: 이 어노테이션은 해당 메서드가 비동기적으로 실행됨을 나타냅니다.

 

@SchedulerLock(name = "Update_User_Grade", lockAtLeastFor = "PT10S"): 이 어노테이션은 spring-task-scheduler-lock 라이브러리에서 제공하는 기능으로, 스케줄러 락(lock)을 적용합니다. name 속성은 락의 이름을 지정하고, lockAtLeastFor 속성은 최소한으로 유지할 락의 시간을 나타냅니다. 여기서는 10초로 설정되어 있으므로, 해당 락은 최소 10초 동안 유지됩니다.

 

Spring Quartz

 

Scheduler보다는 조금더 세밀하게 작업을 할 수있게 도와줍니다. 사용하기 위해서는 의존성을 추가해야합니다.

Quartz의 Job의 필수적인 요소는 JobJobDetailTrigger로 3가지입니다.

implementation "org.springframework.boot:spring-boot-starter-quartz"

 

@Configuration
public class CollectJob implements Job {

  private final CollectService collectService;

  public CollectJob(CollectService collectService) {
    this.collectService = collectService;
  }

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    System.out.println("[Collect] collect Job Start...");
  }
}

Job : 실제로 실행되는 로직이 있는 곳입니다. Quartz에서 interface로 제공하며 해당 interface를 구현하면됩니다.

 

@Bean
public JobDetail tistoryJobDetail() {
return JobBuilder.newJob().ofType(CollectJob.class)
    .storeDurably()
    .withIdentity("job_detail")
    .withDescription("Invoke Tistory Job service...")
    .build();
}

JobDetail : Job을 실행시키기 위한 구체적인 정보를 가지고 있는 인스턴스입니다. JobBuilder API를 통해 만들 수 있습니다. Job에 대한 설명 Job의 ID 등을 설정할 수 있습니다.

 

@Bean
public Trigger tistoryTrigger(@Qualifier("tistoryJobDetail") JobDetail job) {
return TriggerBuilder.newTrigger().forJob(job)
    .withIdentity("tistory_job_trigger")
    .withSchedule(cronSchedule("0 0 9 * * ?")
        .inTimeZone(TimeZone.getTimeZone("Asia/Seoul")))
    .build();
}

Trigger : Trigger는 Job이 실행되는 실행 조건을 가지고 있는 인스턴스입니다. TriggerBuilder API를 통해 만들 수 있습니다. 조건으로 단순히 특정 시간 간격으로 할 수 있으며 Cron으로도 작성할 수 있습니다.

spring:
  quartz:
    job-store-type: memory

apllication.yml 설정까지 하면 사용할수 있습니다.

 

Quartz 장점

  • 테ㅇㅣ터베이스를 기반으로 클러스터링 기능을 제공
  • 기본적으로 여러가지 플러그인을 제공

단점

  • 클러스터링 기능을 제공하지만? 단순한 랜덤 방식임
  • 스케줄링 실행에 대한 이력을 보관하지 않음

'프레임워크 > 스프링' 카테고리의 다른 글

Mockito와 BDDMockito  (0) 2024.03.20
[Spring] MockMvc  (0) 2024.03.18
[Spring] 프로메테우스, 그라파나 아키텍처 사용  (0) 2024.02.16
[Spring] actuator  (0) 2024.02.15
[SpringBoot] 라이브러리 관리  (0) 2023.03.11