일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- MongoDB
- dynamic query
- 파이썬 소스
- smart cast
- oracle
- 유사코드
- 프로젝트
- jsp
- 오라클
- hyperledger
- 초대장
- 오라클 디비
- 파이썬
- K6
- 문법 정리
- 자바 프로젝트
- c#
- gradle
- 티스토리
- auto configure
- 리눅스
- 운영체제
- 백준 알고리즘
- SQL
- 알고리즘
- resilience4j
- JVM
- spring
- 학점
- 자바
- Today
- Total
모종닷컴
Quartz Job Scheduling 1편 - 소개 및 간단한 예제 본문
아주 예전부터 Quartz에 대한 글을 써야지 생각만 하고 어느새 잊어버렸는데요. 이번 회사 동료가 Quartz 적용을 한 발표를 하는데 너무 오래전에 본 내용이라 기억이 하나도 안나네요.. 그래서 기억좀 되살릴겸 Quartz 정리를 좀 해보았습니다.
Quartz Job Scheduling 란?
Quartz Job Scheduling 컴포넌트
주요 컴포넌트 설명
- Scheduler Factory – Scheduler Factory는 Scheduler 인스턴스 생성을 맡고있습니다. quartz.properties 파일의 내용을 기반으로 스케줄러 인스터스를 생성합니다.
- Scheduler – Quartz Scheduler의 메인 인터페이스입니다. Job의 세부 정보(JobDetail)과 Trigger 레지스트리를 관리합니다. 또한 Job과 관련된 Trigger가 발생되었을 때 Job 실행을 책입집니다.
- Quartz Scheduler - Quartz의 핵심입니다. Scheduler 인터페이스를 간접구현하고 있으며, Trigger를 사용하여 Job을 스케줄링 하는 방법을 지니고 있습니다.
- Scheduler Thread – Trigger를 발생시키는 작업을 수행하는 스레드입니다. Job Store에 연결해 실행시킬 다음 Trigger를 가져옵니다.
- Job – Job은 수행할 작업을 나타내기 때문에 실행이 될 task에서 구현해야 하는 가장 중요한 인터페이스입니다.
- JobDetail - JobDetail은 주어진 Job 인스턴스의 상세 속성을 전달합니다. Quartz는 Job 인스턴스를 저장하지 않지만 JobDetail을 사용하여 Job 인스턴스를 정의할 수 있습니다.
- Trigger – 모든 트리거에 공통적인 속성을 가진 기본 인터페이스입니다. Job 실행을 예약하는 데 사용되는 메커니즘입니다. Job과 Trigger의 관계는 1:N입니다. 즉 많은 트리거가 동일한 Job을 가리킬 수 있지만, 하나의 트리거는 하나의 Job만 가리킬 수 있습니다.
- ThreadPool – 실행이 될 Job은 스레드 풀에 전달됩니다.
Optional 컴포넌트
- Job Store – Job과 Trigger에 대한 저장 메커니즘을 제공하는 클래스에 의해 구현되는 인터페이스입니다. 저장은 메모리와 디비로 나뉘는 것 같습니다.
- Job Listener - JobDetail이 실행될 때 알림을 받을 클래스에 의해 구현되는 인터페이스입니다. 스케줄러에 연결되어 있으며 실행 전후에 호출되는 메서드가 있습니다.
- Job Trigger - JobListener와 유사합니다. 트리거가 실행될 때 알림을 받고자 하는 클래스에 의해 구현되는 인터페이스입니다.
https://www.javarticles.com/2016/03/quartz-scheduler-model.html
https://examples.javacodegeeks.com/enterprise-java/quartz/java-quartz-architecture-example/
Spring Boot에서도 지원해주는 Quartz Scheduler
spring.quartz.job-store-type=jdbc
jdbc 스토어가 사용될 때 테이블 생성이 필요할 텐데 아래 프로퍼티를 설정하면 시작하면서 초기화될 것입니다.
spring.quartz.jdbc.initialize-schema=true
Quartz 라이브러리와 함께 표준 스크립트를 사용하여 데이터베이스가 초기화되는데, 커스텀한 스크립트를 적용하고 싶다면 spring.quartz.jdbc.shcema를 사용하면 됩니다.
Quartz Scheduler 구성은 Quartz 설정관련 프로퍼티를 이용하여 커스터마이징 할 수 있습니다.
https://docs.spring.io/spring-boot/docs/2.0.0.M3/reference/html/boot-features-quartz.html
Quartz 사용해보기
spring-boot-starter-quartz를 사용하면 Scheduler는 자동으로 등록된다 했으니 Job이랑 Trigger만 생성해주면 자동 생성된 Scheduler에 자동 등록된다는 것으로 이해했으므로 Job과 Trigger만 생성해줘 보겠습니다.
Dependency
implementation 'org.springframework.boot:spring-boot-starter-quartz'
Property Set
jobStore는 두 가지 유형이 가능합니다. in-memory에 올려서 테스트할 거라면 추가 프로퍼티 세팅은 필요 없으나, jdbc 기반을 사용한다면 아래와 같이 설정을 하도록 해야 합니다. initialize-schema 프로퍼티가 스프링 부트 문서에 나와있는 부분이랑 좀 달랐어요.. 설명을 대충 보니 always를 쓰면 될 것 같아요
## Quartz Properties
quartz:
job-store-type: jdbc # jdbc
jdbc:
initialize-schema: always # Quartz 필수 테이블 자동 생성
Job 정의하기
class TestJob: QuartzJobBean() {
override fun executeInternal(context: JobExecutionContext) {
val jobDateMap = context.jobDetail.jobDataMap
log.info { "name = ${jobDateMap["name"]}, 현재 시각 : ${LocalDateTime.now()}" }
}
}
JobListener 추가
@Component
class TestJobListener : JobListener {
override fun jobExecutionVetoed(context: JobExecutionContext?) {
}
override fun getName(): String = this::class.java.name
override fun jobToBeExecuted(context: JobExecutionContext) {
val jobName = context.jobDetail.jobClass.name
log.info("$jobName 실행 예정.")
}
override fun jobWasExecuted(context: JobExecutionContext, jobException: JobExecutionException?) {
val jobName = context.jobDetail.jobClass.name
log.info("$jobName 실행 완료")
}
}
JobDetail, Trigger 생성 & JobListener 등록
@Configuration
class QuartzConfig(
@Lazy val schedulerFactoryBean: SchedulerFactoryBean,
val testJobListener: TestJobListener
) {
@PostConstruct
fun addListeners() {
schedulerFactoryBean.scheduler
.listenerManager
.addJobListener(testJobListener)
}
@Bean
fun testJobDetail(): JobDetailFactoryBean {
val jobDataMap = JobDataMap()
jobDataMap["name"] = "mojong"
return JobDetailFactoryBean().apply {
setJobClass(TestJob::class.java) // 어떤 Job에 대한 JobDetail 인지 명시
setDescription("Invoke Test Job") // 설명
setDurability(true) // 필수인 듯
setJobDataMap(jobDataMap)
}
}
@Bean
fun testJobTrigger(jobDetail: JobDetail): SimpleTriggerFactoryBean {
return SimpleTriggerFactoryBean().apply {
setJobDetail(jobDetail)
setRepeatInterval(60 * 1000) // 1분마다
setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY) // 계속
}
}
}
테스트 결과
잘 실행이 되는 것 같습니다. jdbc 유형의 jobStore를 사용하면 QRTZ_JOB_DETAILS 테이블과 QRTZ_TRIGGERS 테이블, QRTZ_SIMPLE_TRIGGERS 테이블을 한번 구경해보도록 하죠
이번 글에서는 Quartz Scheduler에 대한 간단하게 이해하고, Spring에 적용해보는 예제를 다뤄보았습니다. 다음 2편에서는 Quartz를 좀 더 다양하게 활용하는 글을 써보도록 하겠습니다.
긴 글 읽어주셔서 감사합니다. 다음 편에 보아요.
'Programming > Spring' 카테고리의 다른 글
멀티 모듈 프로젝트에서 다중 프로퍼티 파일 다루기 (0) | 2022.09.11 |
---|---|
Mock Layer (0) | 2022.08.17 |
PreAuthorize 우선순위 (0) | 2022.08.02 |
Spring AOP vs AspectJ (0) | 2022.07.27 |
스프링 프록시 못된 녀석 - 2편 (프록시 생성 방식) (0) | 2022.07.17 |