반응형
Spring-Batch의 기본 개념을 정리하고, 간단한 실습 환경부터 연습해보는 포스팅입니다
참고
Spring-Batch 공식문서(4.3.3 기준)
https://docs.spring.io/spring-batch/docs/4.3.3/reference/html/
이동욱님의 블로그
https://jojoldu.tistory.com/324?category=902551
1. 메타 테이블 ERD
2. Job 메타 테이블 소개
2-1. BATCH_JOB_INSTANCE
- 속성
컬럼명 설명 JOB_INSTANCE_ID BATCH_JOB_INSTANCE 테이블의 PK VERSION 해당 레코드가 update 될때마다 1씩 증가합니다 JOB_NAME 생성한(실행한) Job 이름 JOB_KEY 동일한 Job이름의 JobInstance는 Job의 실행시점에 부여되는 고유한 JobParameter의 값을 통해 식별됩니다
그리고 이렇게 식별되는 값의 직렬화(serialization)된 결과를 JOB_KEY라는 값으로 기록됩니다 - BATCH_JOB_INSTANCE는 JobParameter에 따라 생성되는 테이블입니다
- JobParameter란?
- SpringBatch가 실행될 때 외부로 부터 주입받는 값
- 같은 Job이여도 JobParameter가 다르면 BATCH_JOB_INSTACNE 테이블에 레코드가 추가되고, 다르다면 추가되지 않습니다
- 예제: JobParameter로 requestDate를 입력받아 로그로 출력하는 Job 생성
// Example JobParameters @Slf4j @RequiredArgsConstructor @Configuration public class SimpleJobConfiguration { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean public Job simpleJob() { return jobBuilderFactory.get("simpleJob") .start(simpleStep1(null)) .build(); } @Bean @JobScope public Step simpleStep1(@Value("#{jobParameters[requestDate]}") String requestDate) { return stepBuilderFactory.get("simpleStep1") .tasklet((contribution, chunkContext) -> { log.info(">>>>> This is Step1"); log.info(">>>>> requestDate = {}", requestDate); return RepeatStatus.FINISHED; }) .build(); } }
- job을 생성하고 Step을 등록할때 simepleStep1에 null을 파라미터로 입력 ( @Value 어노테이션으로 매핑되기 때문에 null을 입력해도 됩니다 )
- simpleStep1에 @JobScope 어노테이션 추가
- simpleStep1의 파라미터로 @Value("#{jobParameters[requestDate]}") String requestDate 추가
- Program Arguments에 requestDate=20210904라는 값을 넣고 실행시키면 정상 실행되고 아래 처럼 레코드가 추가된 것을 확인 할 수 있습니다
- 여기서 다시 한 번 실행시키면? 위에서 설명한 것 처럼 같은 JobParameters로는 레코드 추가가 안되고 정상적으로 실행조차 안되는 것을 확인할 수 있습니다
Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={requestDate=20210904}. If you want to run this job again, change the parameters.
- 결론: 동일한 Job이 Job Parameter가 달라지면 그때마다 BATCH_JOB_INSTANCE에 생성되며, 동일한 Job Parameter는 여러개 존재할 수 없습니다
2-2. BATCH_JOB_EXECUTION
- BATCH_JOB_INSTANCE 테이블이 Job의 실행단위를 구분짓는 것이라면 BATCH_JOB_EXECUTION 테이블은 그 실행단위에 대한 실행횟수(1번 또는 1번이상)를 나타내는JobExecute에 관한 정보를 담고 있습니다
- 속성
속성 설명 JOB_EXECUTION_ID JobInstance에 대한 실행횟수(JobExecution)를 고유하게 식별될할 수 있는 기본 키입니다. VERSION 해당 레코드가 update 될때마다 1씩 증가합니다 JOB_INSTANCE_ID 실행된 JOB_INSTANCE_ID(BATCH_JOB_INSTANCE table) CREATE_TIME 실행(Execution)이 생성된 시점을 TimeStamp 형식으로 기록합니다 START_TIME 실행(Execution)이 시작된 시점을 TimeStamp 형식으로 기록합니다 END_TIME 실행이 종료된 시점을 TimeStamp으로 기록합니다
성공 또는 실패와 상관없이 순수히 끝난 시점을 의미STATUS 실행의 상태를 COMPLETED, STARTED, FAILED 와 같은 미리 정의된 Enum 값으로 기록
org.springframework.batch.core.BatchStatusEXIT_CODE 실행 종료코드를 COMPLETED, NOOP, FAILED 와 같은 Enum 값으로 기록
org.springframework.batch.core.ExitStatusEXIT_MESSAGE 정상적으로 종료되지 않았을 경우에 대한 상세 메시지 LAST_UPDATED 실행(Execution)이 마지막으로 영속(persisted)에 놓인 시점을 TimeStamp 형식으로 기록 JOB_CONFIGURATION_LOCATION ...? - STATUS vs EXIT_CODE
- STATUS는 배치의 실행 상태 그대로를 나타내고 EXIT_CODE는 배치가 종료될 때의 상태 값을 나타냅니다
- 만약 어떤 STEP도 정의되어있지 않다면 STATUS는 COMPLETE이지만 EXIT_CODE는 NOOP가 됩니다
- STATUS vs EXIT_CODE
- JOB_EXECUTION와 JOB_INSTANCE는 부모-자식 관계
- 즉 JOB_EXECUTION table은 자신의 부모 JOB_INSTACNE가 성공/실패했던 모든 내역을 갖고 있습니다
- 단 같은 JobParameters에 대해 새로운 JOB_INSTANCE가 생기지 않았을 경우, JOB_EXECUTION 역시 기록되지 않습니다
- 예제: 같은 Job안에 두번째 Step을 추가
// Add Step2 @Slf4j @RequiredArgsConstructor @Configuration public class SimpleJobConfiguration { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean public Job simpleJob() { return jobBuilderFactory.get("simpleJob") .start(simpleStep1(null)) .next(simpleStep2(null)) .build(); } @Bean @JobScope public Step simpleStep1(@Value("#{jobParameters[requestDate]}") String requestDate) { return stepBuilderFactory.get("simpleStep1") .tasklet((contribution, chunkContext) -> { throw new IllegalArgumentException("step1에서 실패"); }) .build(); } @Bean @JobScope public Step simpleStep2(@Value("#{jobParameters[requestDate]}") String requestDate) { return stepBuilderFactory.get("simpleStep2") .tasklet(((contribution, chunkContext) -> { log.info(">>>>> This is Step2"); log.info(">>>>> requestDate = {}", requestDate); return RepeatStatus.FINISHED; })) .build(); } }
- simpleJob에 next 메서드를 이용해 simpleStep2를 추가했습니다
- 기존의 simpleStep1에서는 runtimeException을 던지게 변경
- Program Arguments를 requestDate=20210904에서 requestDate=20210905로 변경
- 변경하지 않으면 위에서 발생했던 JobInstanceAlreadyCompleteException 예외가 나오게 됩니다
- 실행 결과
java.lang.IllegalArgumentException: step1에서 실패
- 당연히 step1에서 RuntimeException을 던졌기 때문에 해당 Exception이 발생하며 종료되었습니다
- 같은 Job에서 다른 JobParametes가 실행되었기 때문에 BATCH_JOB_INSTANCE table에는 레코드가 추가
- BATCH_JOB_EXECUTION table
- JOB_EXECUTION_ID = 5 인 레코드를 보면 STATUS:FAILED, EXIT_CODE:FAILED로 기록되어 있으며 EXIT_MESSAGE가 위 로그에서 봤던 오류내용이 기록되어있는 것을 확인할 수 있습니다
- 위의 정의된 코드중 STEP1에서 발생시키던 RuntimeException을 다시 정상적으로 수행되게 수정한 후 실행시켜 보겠습니다
- 같은 JobParameters로 실행시켜보면 6번째 로우에서 보이는 것 처럼 같은 JOB_INSTANCE_ID를 가진 STATUS가 COMPLETED 상태의 레코드가 기록된 것을 확인 할 수 있습니다
- 결론: Spring Batch는 동일한 Job Parameter로 성공한 기록이 있을때만 재수행이 안된다
2-3. JOB 개념 정리
- Job: 하나의 실행 단위 ( "simpleJob" )
- JobInstance: JobParameters 단위로 생성되는 Job ( "requestDate=20210904 로 실행된 simpleJob" )
- JobExecute: 생성된 JobInstance의 작업 시도 내역 ( "requestDate=20210904 로 실행된 simpleJob의 1번째, N번째 시도" )
2-4. BATCH_JOB_EXECUTION_PARAMS
- 입력받은 JobParameters에 대한 모든 기록이 담겨있는 테이블
- 속성
속성 설명 JOB_EXECUTION_ID BATCH_JOB_EXECUTION 테이블의 PK입니다 ( 외래 키 ) TYPE_CD JobParameters의 타입 유형, null 값이 올 수 없음 KEY_NAME 매개 변수의 키 ( program argument로 입력한 키 ) STRING_VAL 유형이 문자열인 경우 매개변수 값입니다 DATE_VAL 유형이 날짜인 경우 매개변수 값입니다 LONG_VAL 유형이 긴 경우 매개변수 값입니다 DOUBLE_VAL 유형이 이중인 경우 매개변수 값입니다 IDENTIFYING 같은 JobParameters를 구분할 수 있는지 Flag인거 같은데... 추후 더 알아보겟습니다
2-5. BATCH_JOB_EXECUTION_CONTEXT
- 작업의 ExecutionContext와 관련된 모든 정보를 기록합니다
- 1개의 JobExecution에 각 JobExecutionContext가 있으며 특정 작업 실행에 필요한 모든 작업 레벨 데이터를 포함합니다
- 이 데이터는 일반적으로 JobInstance"중단된 위치에서 시작"할 수 있도록 실패 후 검색해야 하는 상태를 나타냅니다
- 속성
속성 설명 JOB_EXECUTION_ID BATCH_JOB_EXECUTION의 PK입니다 ( 외래 키 ) SHORT_CONTEXT SERIALIZED_CONTEXT의 버전을 나타내는 문자열 SERIALIZED_CONTEXT 직렬화(serialized)된 전체 컨테스트
728x90
반응형
'Practice > SpringBatch' 카테고리의 다른 글
Day 5. Spring Batch Chunk (0) | 2021.10.07 |
---|---|
Day 4. Spring Batch Scope (0) | 2021.09.09 |
Day 3. Spring Batch Job 흐름 정의 (0) | 2021.09.05 |
Day 1. Spring-Batch 환경 설정 (0) | 2021.09.01 |