[spring batch] Spring batch Job 설정과 실행하기

 

위 그림을 기준으로 지금까지 설명한바로는 Spring Batch의 Job은 Step들로 이루어진 간단한 컨테이너 같아 보이나 

개발자가 꼭 알아야할 여러가지 옵션과 설정들이 많이 있다

 

그리고 job을 어떻게 실행하고 실행하는 동안 Jbo의 메타데이터가 어떻게 저장되는지에 대해 고려할 사항들이 많다.

 

[Job 설정하기]

Job Interface의 구현체로 여러가지가 있고 각각의 설정이 다르지만 job name, Job Repository, Step list 3개는 꼭 있어야 한다.

 

 

XML에서 Job Repository는 디폴트로 'jobRepository' id를 가르키나 아래와 같이 바꿀 수 있다.

 

 

Step에는 병렬처리를 위한 <split/>, flow 제어를 위한 <decision/> flow 정의 외부화를 위한 <flow/>도 제공한다.

(Step에서 자세히 보자..)

 

Job이 재시작되어야할지 말지는 해당 배치 시나리오가 어떻게 구성되어 있냐에 따라 다르지만 

 

Spring Batch는 개발자에게 몇가지 옵션을 제공해준다.

 

예를 들어 절대 재시작되어서는 안되는 Job이 있다면 아래와 같이 재시작 속성을 강제로 지정할 수 있다.

 

만약 restartable속성이 false인데 Job이 재시작된다면 아래 코드와 같이 JobRestartException 이 발생 할 것이다.

 

 

Job이 실행되는 동안 여러 이벤트들에 대해 알수 있다면 매우 유용할 것이다. 

SimpleJob은 JobListener를 이용해 해당 기능을 제공한다.

 

 

위와 같이 JobExecutionListener를 구현해서 beforeJob, afterJob에 대한 처리를 할수 있고 

 

구현한 Listener는 Job설정에 추가하면 된다. afterJob()는 Job 성공, 실패 여부와 상관없이 이용할 수 있다.

 

Job상속하기

동일하진 않지만 비슷한 설정을 공유하는 Job들이 있다면 Parent Job을 정의해 사용하면 된다. 

 

child job은 parent의 attribute, element와 합쳐진다.

 

아래 예제에서 basejob은 listener를 가지고 있는 abstract job이고

 job1은 basejob의 lisener를 상속받아 자기의 listener와 결합되어 같이 사용할 수 있다

그래서 step1은 2개의 listener를 가지게 되는 것이다.

 

 

Job Parameter Validator

 

xml에 선언된 job이나 Abstractjob의 subclass job에서는 runtime시점에 job parameter를 위한 validator를 사용할 수 있다.

 

기본적으로 DefaultjobParametersValidator를 제공해주며 직접 만들어서도 사용가능하다.

 

 

 

JAVA Config

 

Spring 3부터 XML이 아닌 Java로 설정이 가능하듯이 spring batch 2.2.0부터 batch job설정도 java config로 처리할 수 있다.

 

java 기반의 설정을 하기 위해서는 @EnableBatchconfiguration annotation과 2개의 Builder가 필요하다.

 

@EnableBatchProcessing annoation은 다른 @Enable* annotation들과 유사하게 동작하는데 batch job들의 기본 설정을 제공한다.

 

설정을 위한 핵심 인터페이스는 BatchConfigurer이고 default implementation은 

 

JobRepository에 필요한 Datasource와 같은 기본 기능들을 처리해준다.

 

기본 설정이 처리되고 나면 job 설정을 위한 builder factory를 사용할 수 있다. (JobBuilderFactory  / StepBuilderFactory)

 

 

 

[JobRepository 설정하기]

 

jobExecution, StepExecution과 같은 Spring Batch Domain object의 persistence layer에 대한 다양한 CRUD 연산을 사용하기 위해 

 

jobRepository를 제공한다고 앞서 말했는데 이 기능은 jobLauncher, job, Step이 사용하기 위해 필요한 기능이다.

 

batch namespace는 jobRepository의 구현을 추상화 시켜놨지만 아래와 같이 몇가지 설정가능한 옵션들이 있다.

Id 속성빼고는 필수값이 아니지만 max-varchar-length나 table prefix를 변경해서 사용할 수 있고 변경안하면 위 값들이 default로 사용된다.

 

JobRepository의 트랜잭션 설정

 

기본 설정을 사용하면 job repository 가 처리될때 자동으로 transactional advice가 적용되어서 

 

실패 후 재시작 여부 같은 상태를 포함하는 batch meta data의 정합성을 보장해 주려 한다.

 

Default Isolation Level은 SERIALIZABLE이고 아래와 같이 변경 가능하고 transactional advice도 변경가능하다.

 

 

In-Memory Repository

 

Job meta data처리에 낭비되는 리소스나 속도를 향상시키기 위해 DB를 사용하기 싫을 때를 위해

 

 in-memory Map version의 job repository를 제공해준다.

 

Job repository에 저장된 값들을 통해서 Job에 대한 상태, 속성들에 대한 검증이 이루어 지는데 

 

in-memory는 휘발성이므로 데이터가 날라가버리면 같은 파라미터값을 가진 job instance가 동시에 실행될 수 있으므로 

 

multi-threaded job이나 partition된 step에서는 제대로 동작안할 수도 있다.

 

그러므로 Test환경에서도 ResourcelessTransactionManager를 사용하는게 낫다.

 

 

Non-standard Database Type 사용한 Job Repository

JobRepositoryFactoryBean을 이용해 사용할 수 있다. 

JobRepositoryFactoryBean은 DataSource로 부터 자동으로 database를 탐지한다.

Standard 와 Non-standard의 가장 큰 차이점은 pk 자동증가이므로 incrementerFactory를 이용해 꼭 override해서 구현해야한다.

만약 위 방법으로 잘 처리되지 않는다면 일반적은 Spring 개발 방법으로 SimplejobRepository 인터페이스를 상속한 

여러 DAO구현체를 만들어서 사용하면 된다.

 

[JobLauncher 설정하기]

 

JobLauncher interface를 구현한 기본 구현체는 SimpleJobLauncher로 실행하기 위해서는 JobRepository에 대한 dependency가 필요하다.

 

JobExecution을 획득하고 나면 Job의 execute 메소드를 통해 최종적으로 호출한놈에게 JobExecution을 돌려준다.

그런데 만약 HTTP 요청을 통해 실행하려한다면 SimpleJobLauncher는 비동기적으로 즉시 호출한놈에게 응답을 줘야한다.

그렇지 않으면 배치처리가 끝날때까지 Http 요청이 오랫동안 유지되어야 한다.

SimpleJobLauncher는 아래와 같이 TaskExecutor를 통해 비동기적으로 응답할수 있도록 설정할 수 있다.

 

Spring의 TaskExecutor 인터페이스의 어떤 구현체도 jobs을 비동기적으로 실행하도록 사용할 수 있다.

 

[Job 실행하기]

Job을 실행하기 위해서는 최소 2가지가 필요하다. Job과 실행하기 위한 JobLauncher.

위 두개는 동일한 Context나 다른 Context를 포함할 수 있다. 

예를 들어 각 Job이 새로운 JVM에 의해 instance화 된 후 command line을 통해 실행되었다면 

모든 잡은 자신만의 JobLauncher를 가지고 있고 

httpRequest scope내의 web container에서 실행된 job들은 1개의 JobLauncher만 있을 것이다.

 

Command Line으로 job 실행하기

enterprise scheduler로 job을 실행하길 원한다면 command line이 주요 방법중 하나이다.

왜냐하면 대부분의 scheduler들이 shell script를 통해 직접 system process 동작을 작동한다.(요부분 번역 확인 필요)

This is because most schedulers (with the exception of Quartz unless using the NativeJob) work directly with operating system processes, primarily kicked off with shell scripts

Perl, Ruby나 ant, maven과 같은 빌드 툴을 이용해 shell script로 java process 실행할 수 있는 많은 방법이 있다

그러나 대부분의 사람들이 schell script에 익숙하기 때문에 여기에 포커스를 두고 만들었다.

 

CommandLineJobRunner

script로 JVM에서 Job을 실행하려면 class와 main method가 필요하다(entry point).

Spring Batch는 CommandLineJobRunner를 통해 위 기능을 제공해준다.

CommandLineJobRunner는 4가지 Task를 수행하는데

1. 적절한 ApplicationContext load

2. command line 인자를 JobParameter로 변환

3. command 인자에 맞는 job 찾기(locate)

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

4. application context가 제공하는 JobLauncher로 Job 실행

 

위 기능을 command의 인자값으로만 처리하고 command의 인자로는 아래 2개가 필요하다.

Job Path - applicationContext를 생성하는데 사용할 xml의 경로

Job Name - 실행할 job 이름

 

bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay schedule.date(date)=2007/05/05

(위 command는 간단하게 표현한거고 classpath나 jar는 알아서 하도록..)

첫번째 인자 endOfDayjob.xml은 job을 가지고 있는 spring applicationContext 설정파일이고

두번째 인자 endOfDay는 job name이다.

마지막 인자 "schedule.date(date)=2007/05/05"는 JobParameter로 처리될 것임

 

위 예제는 CommandLineJobRunner의 필수 요소중 2가지인 Job, JobLauncher를 보여주기 위한 설정이고 이 외에 여러 필수 요소들이 있다.

 

ExitCodes

command-line으로 배치잡을 수행할 때 엔터프라이즈 스케쥴러들이 주로 사용된다.

근데 대부분 스케쥴러들은 단순히 프로세스 레벨에서만 작동해서 알수있는 정보로 

자신을 invoking한 shell script 정도만 관련 정보로 가지고 있다.

이럴 경우 스케쥴러에게 job의 성공 실패 여부는 return code밖에 없다. ( 0 : 성공, 1 : 실패)

 

근데 만약 job A가 4를 return해 job B를 시작하고 B는 5를 return해 job C를 시작한다면?

이런 경우를 위해 spring batch에서는 ExistStatus를 ecnapsulated해서 제공준다.

Exit Code의 가장 중요한 점은 Exit Code는 framework(or Developer)에 의해 셋팅되는 exit code property가 있다는 것과 

JobLauncher의 return값인 JobExecution의 일부로서 return 된다는 것이다

CommandLineJobRunner는 ExitCodeMapper 인터페이스를 이용해 String을 number로 변경해준다.

 

ExitCode의 속성은 exitCode-string, exitDescription-string 인데 commandline으로 실행한 경우

os process level에서는 number 0/1로 성공/실패를 체크하기 때문에 저렇게 mapper를 만들어 놨다. 

SimpleJvmExitCodeMapper를 소스를 봐봐 (org.springframework.batch.core.launch 패키지 소스는 확인해봐야되..)

 

 

Web Container에서 JOB 실행하기

command-line보다는 HttpRequest로 job을 실행하는게 더 좋은 방법이다.

여러 케이스에서 reporting, ad-hoc job running, web application 을 통해 사용하고 있는데 

긴 시간동안 수행되는 배치 잡의 경우 비동기적으로 job을 실행을 보장하는게 가장 중요하다.

아래 소스를 보면 Controller에서 JobLauncher를 이용해 비동기적으로 job을 실행하고 즉시 JobExecution을 return해준다.

Job이 계속 수행되고 있더라도 nonblocking으로 동작하기 때문에 컨트롤러는 HttpRequest에 대해 즉시 응답 가능하다

(Job이 비동기적으로 실행되는 것이지 HttpRequest가 비동기 적인것은 아니다

CallableController와는 다른 것으로 HttpRequest에 의해 Job 1이 실행되었고 Http는 response를 계속 기다리고 있고 

Job 1이 진행중인 상황에또 다른 HttpRequest에 의해 job 2 실행 요청이 오면 Job 2를 실행시켜준다. Job에 대한 비동기 처리임)

 

 

 

[Advanced Meta-Data Usage]

앞서 JobLauncher와 JobRepository 인테페이스에 대해 확인해봤는데 간단한 job 실행시 처리되는 기본적인 CRUD연산 관련 batch domain도 살펴보자.

JobLauncher는 JobRepository를 통해 새로운 JobExecution Object를 만들고 실행한다.

Job과 Step의 구현체는 job이 실행되는 동안의 상태를 JobRepository를 이용해 update한다. 

(이때 Job과 Step은 동일한 JobRepository를 사용해야함)

수백개의 배치 job과 복잡한 스케쥴링이 필요한 대용량 배치 환경에서는 좀 더 많은(advanced한) meta data에 대한 접근이 필요하다.

 

 

Querying the JobRepository

 

실행된 job에 대한 정보를 찾기 위해 JobExplorer interface를 이용해 job repository를 조회해볼 수 있다.

 

 

interface를 보다시피 JobExplorer는 JobRepository의 readonly 버전이다

 

JobRepository의 datasource나 속성들을 변경할 수 있다고 했는데 그럴 경우 아래와 같이 jobexplorer도 변경한 속성으로 맞춰줘야 한다

 

 

[JobRegistry]

 

JobRegistry는 필수요소는 아니지만 현재 어떤 job이 사용가능한지 확인하고 싶을때나 

 

여러 applicationcontext에서 생성된 job들을 한곳으로 모으거나 할때 유용하다.

 

Custom jobRegistry로 등록된 job의 이름이나 속성들을 조작할수도 있다. 

 

spring batch에서 제공해주는 jobregistry는 job name으로 job instace를 찾아주는 간단한 map기반의 구현체이다.

 

 

jobRegistry를 자동으로 등록해주는데는 

 

1. JobRegistryBeanPostProcess를 이용하는 방법과 

 

2. AutomaticJobRegistrar를 이용하는 방법이 있다.

 

JobRegistryBeanPostProcess

 

생성된 잡을 모두 등록할 수 있는 bean post-processor로 child context를 포함한다.

 

 

AutomaticJobRegistrar

child context를 생성하고 child context에 선언된 job을 등록하는 lifecycle 관리 component로 

이걸 사용하면 job registry에 unique한 job 이름을 전역적으로 사용할 수 있다.

만약 xml에 선언된 job의 itemreader이름을 reader로 했는데 해당 xml이 다른 파일에서 전부다 import된다면 

'reader'는 충돌나거나 다른것으로 override될꺼지만 automaticregsistrar은 이걸 방지해 준다.

이걸 사용하기 위해서는 ApplicationContextFactory와 JobLoader를 선언해줘야 한다 

jobLoader는 child context의 lifecycle을 관리하고 job들을 jobregistry에 등록하는 놈이다.

ApplicationContextFactory는 ClassPathXmlApplicationContextFactory를 이용해 child context를 생성한다. 

이 팩토리는 parent context에 있는 설정을 child로 내려버리므로 

PropertyplaceholderConfigurer나 AOP로 child 설정을 재정의 할 필요가 없다.

 

[JobOperator]

JobRepository에 query할 수 있는 연산자 종류들을 JobOperator인터페이스가 제공해준다. 

JobExplorer는 read-only기능이였지만 jobOperator는 stop, restart, summarizing과 같은 다른 유용한 기능을 제공해준다.

 

 

위 연산자들은 JobLauncher, JobRepository, JobExplorer, JobRegistry에 대한 것이기 때문에 

 

JobOperator는 이러한 interface들에 대해 dependency가 있다

 

 

[JobParameterIncrementer]

대부분의 JobOperator들은 설명이 필요없는 자명한 것들이고 궁금한건 문서를 찾아보면 되지만

startNextInstance 는 주목해야 한다.

이 메소드는 Job의 새로운 instance를 start하므로 Job과 JobExecution을 재시작해야할 이슈가 발생할 경우에 매우 유용하다.

JobLauncher통해 새로운 JobInstance를 trigger하기 위해서는 새 JobParameter가 필요한데 

만약 파라미터가 이전 파라미터와 틀리면 startNextInstance는 JobParameterIncrementer를 이용해

기존 Job을 새로운 Job instance에 강제로 맞쳐준다.

 

 

인자로 주어진 JobParameter Object에 대해 필요한 값을 증가시켜 다음 JobParameter를 return한다.

 

이러한 방법은 다음 instance에 대해 어떤 JobParameters값이 생성되어야 할지 framework가 알수 없을 경우에 유용하다.

예를 들어 JobParameter에 date값만 있고 다음 instance가 생성되어야 한다면 날짜 1일 증가되거나 한주가 증가되어야 할 수도 있다

이럴때 Job에 대한 identity를 numeric 값으로 처리하면 된다.

 

 

 

 

Job 종료하기

 

 

JOB ABORT

만약 Job이 restartable로 설정되었다면 job execution이 FAILED인 경우에는 재시작 될 수 있으나 

ABANDONED 상태면 framework에 의해 재시작 되지 않는다.

ABANDONED 상태는 step execution에서 job execution이 skip될수 있다는 마킹용으로 사용된다.

만약 이전 job execution이 실패여서 ABANDONED상태라면 step은 다음 step으로 이동하게 된다.

그리고 kill -9로 프로세스를 죽여버린다면 JobRepository는 프로세스가 죽었는지 아닌지 알 수 없다

이런경우에는 수동으로 Job Status를 조작해줘야한다.

 



출처: https://becko.tistory.com/96 [becko]

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
57 [java, spring] Spring에서 request와 response를 JSON format 으로 한번에 로깅하기 file 졸리운_곰 2021.06.18 178
56 [Spring Boot] 2) Springboot OncePerRequestFilter 와 GenericFilterBean의 차이 file 졸리운_곰 2021.06.18 21
55 [Spring boot] [Spring boot] Spring Boot servlet filter 사용하기 졸리운_곰 2021.06.18 17
54 [SpringBoot] Filter(필터) OncePerRequestFilter간단히 사용하기 file 졸리운_곰 2021.06.18 65
53 [Spring boot] Spring boot 에서 Filter 사용하기 졸리운_곰 2021.06.18 18
52 [Spring Boot] 스프링 부트에 필터를 '조심해서' 사용하는 두 가지 방법 졸리운_곰 2021.06.18 140
51 [스프링 배치] java Spring Batch 졸리운_곰 2020.12.16 77
50 MyBatisPagingItemReader.java 졸리운_곰 2020.11.07 82
49 [JPA] 스프링 데이터 JPA 소개 file 졸리운_곰 2020.11.07 23
48 Spring Batch Example 3 - 청크 지향 프로세싱 file 졸리운_곰 2020.10.24 51
47 Spring Batch Example 2 - 간단한 Job만들기 file 졸리운_곰 2020.10.24 15
46 Spring Batch Example 1 - Spring Batch란? file 졸리운_곰 2020.10.24 55
» [spring batch] Spring batch Job 설정과 실행하기 file 졸리운_곰 2020.10.24 24
44 public class MyBatisPagingItemReader<T> extends AbstractPagingItemReader<T> { 졸리운_곰 2020.10.23 97
43 public class MyBatisBatchItemWriter<T> implements ItemWriter<T>, InitializingBean { 졸리운_곰 2020.10.23 119
42 MyBatisPagingItemReader, MyBatisPagingItemWriter 졸리운_곰 2020.10.23 208
41 [spring batch] 처음 해보는 Spring batch, Tasklet 작성하기 file 졸리운_곰 2020.10.18 15
40 Spring Boot - Properties 사용법 정리 졸리운_곰 2020.10.15 94
39 spring 설정 xml과 소스코드에서 properties 사용하기 졸리운_곰 2020.10.15 14
38 Spring Batch 간단 정리 Sprong Batch 기초를 알아보자 file 졸리운_곰 2020.10.13 47
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED