91일차 Quartz

쿠우·2022년 8월 10일
0

- Quartz

  • 쿼츠란, 오픈소스 스케줄러이다.쿼츠는 자바 환경의 규모와 상관없이 사용이 가능하고 잡 실행에 유용한 스프링 부트 지원과 같이 오래전부터 스프링 연동을 지원하고있다.
  • 메이븐을 통해 관리
  • 배치가 중요하다 불특정 다수의 처리를 해주는게 OLTP

Quartz Job Scheduler 구현 전에 알고 있어야 할 용어 및 개념

1. Job

: 수행시켜야 할 일(Task)

2. JobDetail

: 위1의 Job에 대한 상세정보
- 위 1의 Job을 포함
- Identity : Job Name, Job Group
- Job에 전달할 데이터 설정

3. trigger

: 위 2에 대한 "스케쥴링"(When? How?) 정보
- Identity: name, group 설정
- JobDetail을 언제 시작시킬 건가!?
- 실행주기(반복적 or 1회성) 설정

4. Scheduler

- Scheduling된 Job을 실제 수행시키는 서버프로그램
- Trigger(스케줄링)를 등록하고,
- JobDetail(실제수행시킬Job)을 등록하고
- Trigger대로 JobDetail을 수행시킬 책임

5. Listener (3가지 종류)

(1) Scheduler 자체의 Event Listenning
(2) Job Event Listenning
(3) Trigger Event Listenning

6. Runnable Jar 파일 생성

(1) jar파일 내에서 main메서드를 가진 class를 찾아서 실행시킨다.


-쿼츠의 사용

lombok에서 사용하는 편리한기능 이 어노테이션들과 비슷한 형태로 쿼츠가 사용된다.
-new연산자를 사용하지 않음.

@Data = > 자바 빈즈 클래스를 만드는 어노테이션

1. @Accessors(fluent=true)

-게터와 세터의 메서드를 변수의 이름으로 바꾼다.
-기본적으로 게터와 세터가 있어야한다.

2. @Accessors(fluent=true , chain =true)

-setter의 메서드를 자기자신으로 반환시켜 설정하고싶은 메소드를 연속적으로 부르는게 가능해짐.

@Builder

-builder 메서드를 통해 BuildPatternBuilder를 객체를 생성한다.
-그 상태에서 세터를 이용해 정보 주입
-build 메서드를 통해서 해당 클래스의 객체를 생성한다.

public class Main {

	public static void main(String[] args) {
		
		Person person = Person
						.builder()
						.age(2)
						.name("민들레씨")
						.build();
		
		System.out.println("내 나이는 " + person.age() + " 내 이름은 " +person.name());

		
	}// main

}//end class

@Builder
@Accessors(fluent = true, chain = true)
@Data
class Person{
	private int age;
	private String name;
}// end class

1. job 구현 클래스

  • execute 메서드를 구현하며 jobExecutionContext 객체를 매개변수로 갖는다.
  • 이를 구현하면서 무엇을 하는지 (통계산출, 정산, 요금, 주기적인 데이터 획득에 사용) 6번에 세세하게 적음
  • 잡객체는 스케줄링 될 때 실행되며 생성된다. 스케줄러에 의해 생성되어 주체가 사람이 아니기 때문에 생성자에 매개변수가 없음
@Log4j2
@NoArgsConstructor

// Newly This Object Created Each Execution.
public class JobA implements Job {

	@Override
    public void execute(JobExecutionContext ctx) throws JobExecutionException {
		log.trace("execute({}) invoked.", ctx);
		
		try {
			// Batch Job 구현코드 작성 (통계산출, 정산 ,요금)
			log.info("- Job A -");
		} catch(Exception e) {
			throw new JobExecutionException(e);
		} // try-catch
    } // execute

} // end class

2. Scheduler 객체 생성

  • StdSchedulerFactory.getDefaultScheduler(); 메소드를 통해 얻는다. - 생성
  • 객체를 생성하면 기본적으로 10개의 멀티쓰레드가 된다.
  • Trigger와 JobDetail 생성을 해준 뒤 scheduleJob(잡디테일,트리거) 메소드를 통하여 넣어준다
  • 스케쥴정보가 들어갔으면 start() 메소드를 통하여 실행한다. (결과: 주기적으로 정보를 알려준다.)
//        	============================================
//        	1. To create a Quartz job scheduler
//        	============================================
        	
        	Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

3-1. jobDetail 생성

  • jobDetail 을 생성은 Jobuilder.newJob(~~.class) 을 통해 생성
  • withDescription("~~") 메소드는 잡을 설명해줄 내용을 넣어준다. (잡디테일의 메소드)
  • withIdentity("~~","GROUP_1") / withIdentity(jobKey)메소드는 생성한 잡을 그룹지어준다.(잡디테일의 메소드)
  • usingJobData("","") 메소드는 맵형식으로 데이터를 저장 (잡디테일의 메소드)

//        	============================================
//          2. To create a Quartz job with the associated trigger
//        	============================================

            JobDetail simpleJob = // Quartz Job to be scheduled.
    			JobBuilder.newJob( SimpleJob.class ).
//	    			withIdentity("simpleJob", "GROUP1").
    				withIdentity( JobKey.jobKey("simpleJob", "GROUP1") ).
	    			usingJobData("jobSays", "Hello World!").
	    			usingJobData("myFloatValue", 3.141f).
	    			build();

3-2. Trigger 생성

  • jobDetail 객체를 먼저 생성 해준다.
  • TriggerBuilder.newTrigger() 를 통해 생성
  • withDescription("~~") 메소드는 잡을 설명해줄 내용을 넣어준다. (트리거의 메소드)
  • withIdentity("~~","GROUP_1") / withIdentity(TriggerKey)메소드는 생성한 트리거를 그룹지어준다. (트리거의 메소드)
  • withPriority(1) 메소드는 쓰레드 우선순위를 정한다. (최대 10)
  • startNow() 를 통해 실행을 바로 시킨다. / startAt()중에서 지연구동과 즉시실행을 선택할 수 있음
  • withSchedule() 주기적으로 할지 한 번만 할지 스케줄을 정한다. 이 메서드 안에 또 해당되는 메서드들을 설정해준다.


            Trigger simpleJobTrigger = // Job Scheduling registered to the Quartz Scheduler.
        		TriggerBuilder.newTrigger().
//        			withIdentity("simpleJobTrigger", "GROUP1").
        			withIdentity( TriggerKey.triggerKey("simpleJobTrigger", "GROUP1") ).
        			startNow().
        			withSchedule( 
    					SimpleScheduleBuilder.simpleSchedule().
//							withIntervalInMilliseconds(1000*1L).	// in milliseconds
							withIntervalInSeconds(1).				// in seconds
//    						withIntervalInMinutes(1). 				// in minutes
//    						withIntervalInHours(1).					// in hours
							repeatForever()
							
//    						withRepeatCount(10)
    				).
        			build();

4. ListenerManager 통해 job, Trigger ,Scheduler 의 정보를 얻어낸다.

  • 주기적으로 모니터링하면서 바꿔야할 정보가 있을 때 필요하다.
    (탈퇴한 회원의 정보 보관기간 내에 재이용 확인 시)
  • ListenerManager 객체의 addJobListener(JobListener jobListener) 메소드를 통해 job 정보를 얻음
//        	============================================
//          3. To add each listener with Quartz job, trigger, scheduler
//        	============================================
            
            ListenerManager listenerManager = scheduler.getListenerManager();
            
            listenerManager.addJobListener(new JobListenerImpl());
            listenerManager.addTriggerListener(new TriggerListenerImpl());
            listenerManager.addSchedulerListener(new SchedulerListenerImpl());

4-1. JobListenerImpl / jobListener

( SchedulerListener/TriggerListener 도 있지만 안했숨둥 비슷한 맥락 )

  • JobListenerImpl class 생성시 jobListener 인터페이스를 implements 해준다.
  • getName()메소드는 job리스너의 이름을 정의하라.
  • jobToBeExecuted(JobExecutionContext ctx) 메소드는 실행될 잡에 대한 정보를 얻는다.
  • jobExecutionVetoed(JobExecutionContext ctx) 메소드는 잡이 실행될 수 없는 상황이 되었을 때 정보를 얻는다.
  • jobWasExecuted(JobExecutionContext ctx, JobExecutionException e) 메소드는 과거에 실행되었던 잡에 대한 정보를 얻는다.
@Log4j2
@NoArgsConstructor
public class JobListenerImpl implements JobListener {
	@Override
	public String getName() {
		log.trace("getName() invoked.");	
		return "- JobListener -";
	} // getName

	@Override
	public void jobToBeExecuted(JobExecutionContext ctx) {
		log.trace("jobToBeExecuted({}) invoked.", ctx);
	} // jobToBeExecuted

	@Override
	public void jobExecutionVetoed(JobExecutionContext ctx) {
		log.trace("jobExecutionVetoed({}) invoked.", ctx);
	} // jobExecutionVetoed
	
	@Override
	public void jobWasExecuted(JobExecutionContext ctx, JobExecutionException e) {
		log.trace("jobWasExecuted({}, {}) invoked.", ctx, e);
	} // jobWasExecuted

} // end class

5. 실행 부분!

  • 스케쥴러에 추가할 잡과 잡트리거 넣는 메소드는 .scheduleJob(잡, 트리거) ->(참고: 반환타입 Data )
//        	============================================
//          4. To schedule Quartz Jobs with Job and Trigger
//        	============================================
            
            scheduler.scheduleJob(simpleJob, simpleJobTrigger);
            scheduler.scheduleJob(jobA, jobATrigger);
            scheduler.scheduleJob(jobB, jobBTrigger);

            
//        	============================================
//          5. To start a Quartz Scheduler
//        	============================================
            
            scheduler.start();

6. 실제 사용을 위한 job의 메서드

  • usingJobData로 넘겨준 데이터를 어떻게 사용할 것인가에 대한 대답을 해주는 예제
  • JobDataMap 객체의 getJobDetail().getJobDataMap() 메소드를 이용해 객체에 data를 저장한다.
  • get~type~("key") 을 이용해서 해당 타입에 맞게 저장한 키에 따른 value 값을 반환
  • 받아온 정보들의 가공 후 보여주기 가능
// Newly This Object Created Each Execution.
public class SimpleJob implements Job {

	
	@Override
    public void execute(JobExecutionContext ctx) throws JobExecutionException {
		log.trace("execute({}) invoked.", ctx);
		
		try {
	        JobDataMap dataMap = ctx.getJobDetail().getJobDataMap();
	
	        String jobSays = dataMap.getString("jobSays");
	        float myFloatValue = dataMap.getFloat("myFloatValue");
	
	        log.info("- SimpleJob says: {}, and val is: {}", jobSays ,myFloatValue);
		} catch(Exception e) {
			throw new JobExecutionException(e);
		} // try-catch
    } // execute
	
} // end class

7. jar로 Export

  • package로 만드는게 정석..
  • jar로 만들면 경로가 jar파일 위치부터가 경로의 시작이 된다.
  • (중요) resource의 Build Path를 보면 Excluded 으로 되어있으면 jar로 패키징 될 때 별도의 폴더를 만들어 경로가 위배된다. 따라서 Excluded (None) 설정해준다.
    ->이것을 안하면 log4j2가 리소스로 경로를 잘못 가지고 간다.
  • WAS로 하면 Deployment Assembly에서 설정한 배포조합으로 설정해놓은 경로로 자동으로 만든다.
profile
일단 흐자

0개의 댓글