[Camel in Action] 16-2. Camel Quartz 클러스터 – 분산 환경 배치 스케줄 관리

분산 환경에서 스케줄 중복 실행 문제

여러 서버에서 같은 배치 스케줄을 실행하면 같은 시간에 모두 실행됩니다. 이 경우 동일한 작업이 중복 실행됩니다. Quartz의 클러스터링 기능을 사용하면 데이터베이스를 통해 클러스터 내에서 오직 하나의 노드만 스케줄을 실행합니다.

Quartz 클러스터 DB 설정

Quartz 클러스터는 DB에 스케줄 상태를 저장해 노드 간 조율합니다. Quartz가 제공하는 SQL 스크립트로 테이블을 생성합니다.

# quartz.properties
org.quartz.scheduler.instanceId=AUTO
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
org.quartz.jobStore.dataSource=myDB

# Spring Boot 설정
spring.quartz.job-store-type=jdbc
spring.quartz.properties.org.quartz.jobStore.isClustered=true

Camel에서 Quartz 클러스터 사용

// 클러스터링된 Quartz Camel 라우트
from("quartz2:daily-report?cron=0+0+2+*+*+?&stateful=true")
  .routeId("clustered-daily-report")
  .log("리포트 생성 시작 - 이 노드: ${sys.hostname}")
  .to("bean:reportService?method=generateDailyReport");

stateful=true를 설정하면 Job이 DB에 영속적으로 저장됩니다. 어떤 노드가 이 시간에 살아있든 단 하나만 실행됩니다.

미스파이어 처리

서버가 다운된 동안 실행되어야 했던 스케줄(미스파이어)을 어떻게 처리할지 정책을 설정합니다.

// 가장 최근 미스파이어 한 번만 실행
from("quartz2:daily?cron=0+0+9+*+*+?&misfireInstruction=MISFIRE_INSTRUCTION_FIRE_ONCE_NOW")

// 미스파이어 무시 (다음 정규 실행까지 대기)
from("quartz2:daily?cron=0+0+9+*+*+?&misfireInstruction=MISFIRE_INSTRUCTION_DO_NOTHING")

동적 스케줄 관리

관리자 UI에서 스케줄을 수정하면 클러스터 전체에 즉시 반영됩니다.

// Quartz Scheduler에서 직접 Job 추가/수정
@Autowired
private SchedulerFactory schedulerFactory;

public void updateSchedule(String jobName, String newCron) throws Exception {
  Scheduler scheduler = schedulerFactory.getScheduler();
  TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
  Trigger newTrigger = TriggerBuilder.newTrigger()
    .withIdentity(triggerKey)
    .withSchedule(CronScheduleBuilder.cronSchedule(newCron))
    .build();
  scheduler.rescheduleJob(triggerKey, newTrigger);
}

Leave a Comment