서론
예전에 커뮤니티 사이트에서 글목록을 수집하고 DB에 저장하는 크롤러를 만든적이 있었다. 이 때, 주기적으로 실행하기 위해서 crontab이나 Windows 작업 스케줄러를 사용했다. 이 두개의 스케줄러는 사용하기는 편하지만 프로그램과 스케줄을 별도로 관리해야하기 때문에 관리포인트가 늘어나는 단점이 있다.
그래서, 이번에는 스케줄러를 직접 만들어보려고 하는데 Spring Batch는 써본적이 있기 때문에 이번에는 Quartz로 만들어 보려고 한다.
개발환경
- jdk-11.0.5
- quartz-2.3.2
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
Quartz란?
- Java Scheduling 라이브러리.
- 일련의 작업들을 단발성, 주기성으로 실행할 수 있음.
구성요소
1. JOB
- 실제 작업을 수행하는 객체
- org.quartz.Job 인터페이스를 상속받아 execute 메소드에 수행 로직을 구현
- 같은 그룹에는 동일한 이름을 가진 Job을 생성할 수 없음
2. Trigger
- Job을 수행하기위한 조건(스케줄)을 정의한 객체
- 특정시간, 횟수, 반복주기 등을 설정할 수 있음
* 특정시간 및 횟수: SimpleTrigger
* 주기적으로 반복: CronTrigger
- 같은 그룹에는 동일한 이름을 가진 Job을 생성할 수 없음
- Job : Trigger = 1 : N
3. Listener
- 작업의 시작, 중간, 끝, 에러를 처리할 수 있는 객체
- ScheduleListener와 TriggerListener
소스코드
1. SampleJobExecutor.java
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import sch.listeners.MyScheduleListener;
import sch.listeners.MyTriggerListener;
/**
* Quartz Job
*/
public class SampleJobExecutor implements Job {
private static final SimpleDateFormat TIMESTAMP_FMT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSS");
@Override
public void execute(JobExecutionContext ctx) throws JobExecutionException {
JobDataMap jobDataMap = ctx.getJobDetail().getJobDataMap();
String currentDate = TIMESTAMP_FMT.format(new Date());
String triggerKey = ctx.getTrigger().getKey().toString();
String message = jobDataMap.getString("message");
System.out.println(String.format("[%s][%s] %s", currentDate, triggerKey, message ));
}
}
/**
* Quartz Scheduler 실행
*/
class JobLuacher {
public static void main(String[] args) {
try {
// Scheduler 생성
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.getListenerManager().addJobListener(new MyScheduleListener());
scheduler.getListenerManager().addTriggerListener(new MyTriggerListener());
// Scheduler 실행
scheduler.start();
// JOB Data 객체 생성
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("message", "Hello, Quartz!!!");
// JOB Executor Class
Class<? extends Job> jobClass = SampleJobExecutor.class;
// JOB 생성
JobDetail jobDetail = JobBuilder.newJob(jobClass)
.withIdentity("job_name", "job_group")
.setJobData(jobDataMap)
.build();
// SimpleTrigger 생성
// 4초마다 반복하며, 최대 5회 실행
SimpleScheduleBuilder simpleSch = SimpleScheduleBuilder.repeatSecondlyForTotalCount(5, 4);
SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
.withIdentity("simple_trigger", "simple_trigger_group")
.withSchedule(simpleSch)
.forJob(jobDetail)
.build();
// CronTrigger 생성
// 15초주기로 반복( 0, 15, 30, 45 )
CronScheduleBuilder cronSch = CronScheduleBuilder.cronSchedule(new CronExpression("0/15 * * * * ?"));
CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger()
.withIdentity("cron_trigger", "cron_trigger_group")
.withSchedule(cronSch)
.forJob(jobDetail)
.build();
// JobDtail : Trigger = 1 : N 설정
Set<Trigger> triggerSet = new HashSet<Trigger>();
triggerSet.add(simpleTrigger);
triggerSet.add(cronTrigger);
// Schedule 등록
scheduler.scheduleJob(jobDetail, triggerSet, false);
} catch (ParseException | SchedulerException e) {
e.printStackTrace();
}
}
}
|
cs |
실행결과
마치며
이것으로 간단하게 Quartz로 스케줄러를 만들고 실행하는 방법에 대해서 알아보았다. 만들어보니 Spring Batch보다 훨씬 간단했다. 다만, 스케줄을 Annotation으로 등록할 수 있는 Spring Batch와는 다르게 Trigger 객체를 생성해야하는 번거로움이 있다. 그래도, Quartz가 좀 더 직관적이라 마음에 든다.
'Back-end > JAVA' 카테고리의 다른 글
[JAVA] Quartz 스케줄러 만들기 (3) - Job 강제 종료 (0) | 2020.11.11 |
---|---|
[JAVA] Quartz 스케줄러 만들기 (2) - Listener (0) | 2020.11.10 |
[JAVA] 간단한 HTTP 서버 구축하기 (0) | 2020.11.05 |
[JAVA] 파일 분할 - 용량 단위, 아래에서 위로 ↑ (0) | 2020.10.22 |
[JAVA] 파일 분할 - 용량 단위, 위에서 아래로 ↓ (0) | 2020.10.22 |
댓글