Jenkins 을 스케줄링용도로 사용시 장점

  • Job 추가/삭제/목록 등의 UI를 통해서 쉽게 관리 가능
  • Job 순서에 대한 개런티를 보장함
    (즉 선행된 동일 Job이 끝날때 까지 대기)
  • 다양한 플러기인 제공
  • 클러스터링을 통한 중앙 집중 관리
  • 심플한 Job Flow를 제공
  • 실행 Job 앞뒤로 before, after 처리 가능
  • Java 외에 모든 언어 및 shell를 지원
  • Job 실패 와 성공 유뮤를 UI를 통해서 확인 가능
  • 실행 중인 Job을 취소 할 수 있음.
  • Job 시작/종료 시간을 알 수 있음.


Jenkins 을 스케줄링용도로 사용시 단점

  • 매번 Job를 hard하게  run (java -jar ….)하기 때문에세밀한 스케줄러 타이밍 어려움 (스프링으로 된 Job일 경우 10 ~ 15초 정도 delay)
  • 초 단위 Batch를 정확하게 스케줄링 하기 어려움
  • 비즈니스 로직에 의한 스케줄러 실행 유무가 어려움

하지만 개인적인 생각으로는 특별한 경우를 제외하고는 Quartz 기반으로 다른 기능들을 조합해서 

구현 및 운영하는 것이 좋다고 생각한다.


Jenkins 는 지속적인 통합빌트(C.I) 를 위한 툴의 성격이 강한 이유이다.


Jenkins의 장점으로 거론되는 기능들은 Spring Batch 나 DB 를 이용하여 Job을 관리하는 JDBCJobStore 를 사용하면 구현 가능하다.  


오히려 일반적인 경우 단점이 너무 크다.


Posted by 빨강토끼

spring 을 사용하여 quartz 를 사용하려면 아래와 같은 구조를 흔히 사용하게 된다.




Hello : 개발자가 직접 작성할 비즈니스 컴포넌트.


JobDetailBean : Job과 Job 속성 및 파라미터 정보를 모아놓은 컴포넌트.


TriggerBean : Job 실행 시작, 주기등을 설정하는 컴포넌트.


SchedulerBean : 모든 Job 설정 정보를 갖고 Manager Thread를 생성해서 해당 시간에 Job을 실행하는 컴포넌트.


그리고 각 bean 들을 FactoryBean 을 사용하여 생성한다.


일단 먼저 spring framework 를 설정해야된다.


중요 모듈은 아래와 같다.


모듈 : 설명 

spring-core.jar : 스프링코어 

spring-context-support.jar : Quartz 지원


Maven 으로 설정하기(pom.xml)

<dependency>

  <groupId>org.springframework</groupId>

  <artifactId>spring-core</artifactId>

  <version>4.1.1.RELEASE</version>

</dependency>

<dependency>

  <groupId>org.springframework</groupId>

  <artifactId>spring-context-support</artifactId>

  <version>4.1.1.RELEASE</version>

</dependency>



그리고 당연히 quartz 도 설정해야된다.

http://www.quartz-scheduler.org/downloads


모듈 : 설명

quartz-2.2.1.jar : Quartz 코어 

quartz-jobs-2.2.1.jar : Quartz Job 지원


Maven

<dependency> 

  <groupId>org.quartz-scheduler</groupId>

  <artifactId>quartz</artifactId> 

  <version>2.2.1</version> 

</dependency> 

<dependency> 

  <groupId>org.quartz-scheduler</groupId> 

  <artifactId>quartz-jobs</artifactId> 

  <version>2.2.1</version> 

</dependency>




output



Posted by 빨강토끼

CronTrigger는 앞에서 살펴본 "cron 표현법"을 사용하여 스케줄링 기능을 제공한다.


작업(Job) 실행이 달력 개념을 기반으로 반복된다면  SimpleTrigger보다 CronTrigger가 더 유용하게 사용될 수 있다.


"매주 월요일부터 금요일까지 아침8시” 

"매달 마지막 금요일 새벽1시30분” 


하지만 cron 표현법 보다는 좀 더 자세한 설정이 가능한데 "초(seconds)" 와 "년(year)" 이다.

 필드

 필수

허용  

Special characters

 (seconds)

 Yes

 0-59

 , - * /

 (minutes)

 Yes

 0-59

 , - * / 

 (hours)

 Yes

 0-23

  , - * /

 날짜(day of month)

 Yes

 1-31

  , - * / ? L W

 (month)

 Yes

 1-12 or JAN-DEC

  , - * /

 요일(day of week)

 Yes

 1-7 or SUN-SAT

  , - * / ? L #

 (year)

 No

 empty, 1979-2099

  , - * /


다양한 특수문자 역시 동일하게 사용할수 있다.


* : 모든 값을 의미.

? : 특정 값을 정하지 않음.

- : 범위를 의미. 예) 0-10이면 0부터 10까지.

, : 값을 추가. 0-10,20-30은 0부터 10까지, 그리고 20부터 30까지.

/ : 증분을 의미. 예) 초에 0/15를 사용하면 15초마다(0, 15, 30, 45) .

L : 마지막을 의미. 날짜에 사용하면 월의 마지막 날을 의미. 

    31, 30 또는 28(윤달에는 29).

W : 주중(weekday)를 의미. 날짜와 같이 쓰면 그 날짜가 주중인 날을 의미. 


아래는 몇가지 예를 들어본것이다.



Expression

Meaning

0 0 12 * * ?

매일 12(정오)

0 15 10 ? * *

매일 오전 10 15

0 15 10 * * ?

매일 오전 10 15

0 15 10 * * ? *

매일 오전 10 15

0 15 10 * * ? 2005

2005년에 매일 아침 10 15

0 * 14 * * ?

매일 오후 2 0 ~ 59

0 0/5 14 * * ?

매일 오후 2시부터 2 55분까지 5분마다

0 0/5 14,18 * * ?

매일 오후 2시부터 2 55분까지 5분마다

6시부터 6 55분까지 5분마다

0 0-5 14 * * ?

매일 오후 2시부터 2 5분까지 매분

0 10,44 14 ? 3 WED

매년 3월의 수요일마다 오후 2 10분과 2 44

0 15 10 ? * MON-FRI

월요일부터 금요일까지 오전 10 15

0 15 10 15 * ?

매달 15 오전 10 15

0 15 10 L * ?

매달 마지막 오전 10 15

0 15 10 ? * 6L

매달 마지막 금요일 오전 10 15

0 15 10 ? * 6L 2002-2005

2002년부터 2005년까지 매달 마지막 금요일 오전 10 15

0 15 10 ? * 6#3

매달 3번째 금요일 오전 10 15

0 0 12 1/5 * ?

매달 첫날부터 5일마다 12(정오)

0 11 11 11 11 ?

매년 11 11 오전 11 11



output




소스 : https://github.com/redrebel/Scheduling

Posted by 빨강토끼

Quartz는 먼저 이전글(자바기반 스케줄링 프로그래밍(3) - java.util.java)의 맛집 예와 비교해보겠다.


지금 시간이 오후 2시이고 7시에 맛집에서 식사를 하려고 한다면,

1. 지금부터 5시간후에 가겠다고 맛집에 예약을 해놓는다.(음식도 주문한다)

2. 5시간후에 맛집에 가면 거의 기다리지 않고 바로 먹을 수 있다.


Quartz 의 공식 사이트와 다운로드 할 수 있는 주소는 아래와 같다.

http://www.quartz-scheduler.org/

http://www.quartz-scheduler.org/downloads


모듈 : 설명

quartz-2.2.1.jar : Quartz 코어 

quartz-jobs-2.2.1.jar : Quartz Job 지원



Maven

<dependency> 

  <groupId>org.quartz-scheduler</groupId>

  <artifactId>quartz</artifactId> 

  <version>2.2.1</version> 

</dependency> 

<dependency> 

  <groupId>org.quartz-scheduler</groupId> 

  <artifactId>quartz-jobs</artifactId> 

  <version>2.2.1</version> 

</dependency>


quartz를 사용하기 위해서는 몇가지 알아야되는 것들이 있는데,

그중 Trigger 라는 것이 있다.


이론적인 설명은 구글링을 통하여 각자 알아보길 바란다.


우선 이번 글에서는 Trigger 중 SimpleTrigger 를 설명하고 

CronTrigger 에 대한것은 다음글에 설명하도록 하겠다.


SimpleTrigger : 사용이 간단하며 interval, delay, repeat times등을 설정 할 수 있다.



output



거의 일정한 시간간격으로 실행된다.

Posted by 빨강토끼

public void java.util.Timer.schedule(TimerTask task, Date firstTime, long period)

Parameters: 

task - 스케줄링 되어 실행될 task. 

firstTime - 실행될  task의 처음시각. 

period - task가 실행될 주기(millisecond). 




output


java.util.Timer 는 단점이 있다.

output 을 보면 0.001~0.002초씩 로그시간이 지연이 발생되는것을 알수있다.


자바의 특성과 다양한 플랫폼에서의 구현때문에, 각각의 JVM에서의 Thread 스케줄링의 구현은 일치하지 않는다.

Task는 Runnable 객체로 구현되어 있고 일정시간동안 sleep상태가 된다. 그러면 Timer가 규정된 순간에 task를 깨운다. 그러나 정확한 실행시간은 JVM 의 스케줄링 정책과 현재 얼마나 많은 Thread가 프로세서를 기다리고 있냐에 따라 달라진다.

Task가 지연되는 경우는 크게 2가지이다.

- 많은 수의 쓰레드가 실행되기를 기다리고 있는 경우

- GC 에 의한 지연

각 Timer 객체는 쓰레드를 백그라운드로 시작한다.

이러한 방식은 J2EE 애플리케이션 서버와 같은 환경에서는 바람직하지 않을 것이다.

왜냐하면 이러한 쓰레드들이 컨테이너 영역 내에 있지 않기 때문이다.



예를 들어 

지금 시간이 오후 2시이고 7시에 맛집에서 식사하려고 한다면,

1.지금부터 5시간후에 맛집에가서 식사를 하겠다고 계획을 세운다.

2.5시간후에 맛집에 도착한다.

3.하지만. 이미 손님들이 줄을 서있어서 기다려서 먹어야한다….


이해하기 쉽게 하기 위하여 예를 든것이므로 혹시 잘못 이해하지 않길 바란다.

그럼 나름 정확한 시간간격으로 실행되거나 특정한 날이나 요일등의 달력기반의 스케줄링을 하려면 
어떻게 해야할까?

다음에 설명할 Quartz를 사용하면 된다.


Posted by 빨강토끼

cron 은 오랬동안 사용되어오며 스케줄링 성능의 입증되어온 유닉스의 툴이다.


cron 명령어는 OS마다 다소의 차이가 있지만 리눅스 기준으로


$crontab -e [엔터]


1 2 3 4 5  사용자아이디 명령어

 

1: minute (0-59)

2: hour (0-23)

3: day of the month(1-31)

4: month of the year(1-12) OR jan, feb, mar, apr ...
5: day of the week (0-6)(Sunday=0 or 7) OR sun, mon, tue, wed, thu, fri, sat


순으로 입력하고, 명령어란에 여러분이 만든 어플이나 실행스크립트를 넣어서 사용한다.


예를 들어 아래와 같은 명령이 있다고 하면

#date time sync

0 5 * * * root /usr/bin/rdate -s time.bora.net && /sbin/hwclock -w



매일 , 오전 5시 0분에 시스템의 기준시를 맞추는 동작(/usr/bin/rdate -s time.bora.net && /sbin/hwclock -w)을 하게 된다.


다른 예로는 OS X 에서 아래와 같은 명령은 매1분마다 date.txt 라는 파일에 현재시간을 기록하는 cron 명령이다. 

0/1 * * * * date >> /Users/red/date.txt



0/1 같이 다양한 특수문자를 사용할수 있다.


* : 모든 값을 의미.

? : 특정 값을 정하지 않음.

- : 범위를 의미. 예) 0-10이면 0부터 10까지.

, : 값을 추가. 0-10,20-30은 0부터 10까지, 그리고 20부터 30까지.

/ : 증분을 의미. 예) 초에 0/15를 사용하면 15초마다(0, 15, 30, 45) .

L : 마지막을 의미. 날짜에 사용하면 월의 마지막 날을 의미. 

    31, 30 또는 28(윤달에는 29).

W : 주중(weekday)를 의미. 날짜와 같이 쓰면 그 날짜가 주중인 날을 의미. 


로그 파일 백업이나 주기적으로 간단한 동작을 하는  명령이나 프로세스에 적당하다.



Posted by 빨강토끼

어떤 프로젝트에서 , 특정 시각이나 일정시간 간격으로 job 실행되어야 하는 경우가 있다.


매일 혹은 매월 통계데이터를 만들어야 되는 배치성 업무나, 일정 주기별로 서비스의 상태나 변경사항을 관리자에게 알려줘야되는 업무가 예다.



일반적으로 Java Timer API  crontab, Quartz 구현한다.

( 외에도 다수의 job scheduler library 존재한다.)


나는 PG(Payment Gateway) 개발을 하고 있다.


나의 경우에는 아래와 같은 배치성 업무들이 있다


  • 매일 새벽에 그전날 결제건에 대한 통계생성

  • 외부 PG업체에서 전날의 결제정보를 받아와 우리시스템과의 대사작업 수행

  • 매월 초 이전달 결제에 대한 정산작업

  • 매월 말 이전달 결제에 대한 청구작업 

각 업무의 특성에 맞게 crontab 과 quartz 를 선택하여 사용하고 있다.


자바기반 스케줄링 프로그래밍에 대한 자세한 내용은 아래 페이지를 참조하면 된다.


참조 :

http://archive.oreilly.com/pub/a/java/archive/quartz.html

http://tmwalker.tistory.com/36 (번역)

Posted by 빨강토끼