[Spring Batch] 스프링 배치 기초, 메타 데이터와 도메인
- -
스프링 배치(Spring Batch)
스프링 배치란?
Spring Batch는 대용량 일괄처리의 편의를 위해 설계된 가볍고 포괄적인 배치 프레임워크이다.
로깅/추적, 트랜잭션 관리, 작업 처리 통계, 작업 재시작, 건너뛰기, 리소스 관리 등 대용량 레코드 처리에 필수적인 재사용 가능한 기능을 제공한다.
또한 최적화 및 파티셔닝 기술을 통해 대용량 및 고성능 일괄 작업을 가능하게 하는 고급 기술 서비스 및 기능을 제공한다.
Spring Batch Meta Data
스프링 배치는 배치의 실행 및 관리를 위한 목적으로 여러 도메인들(Job, Step, JobParameters 등)의 정보들을 저장, 업데이트, 조회할 수 있는 스키마를 제공한다.
과거, 현재의 실행에 대한 자세한 정보, 실행에 대한 성공과 실패 여부 등을 일목요연하게 관리함으로서 배치 운용에 있어 리스크 발생시 빠른 대처가 가능하다.
스프링 배치 라이브러리에서 DB 스키마를 제공한다.org.springframework.batch:spring-batch-core
라이브러리의 org.springframework.batch.core
위치에 DB별 스키마 파일이 존재한다.
DB에 맞는 스키마를 복사해서 수동으로 테이블을 생성할 수도 있고 아래와 같이 설정을 통해 자동 생성할 수도 있다.
spring:
batch:
jdbc:
initialize-schema: always # [always || embedded (default) || never]
spring.batch.jdbc.initialize-schema
옵션을 설정한다.always
: 항상 스크립트를 실행한다.embedded
: 내장 DB일 때만 실행되어 스키마가 자동 생성된다.never
: 스크립트를 실행하지 않는다.- 메타 테이블이 생성되어있지 않다면 오류가 발생하여 애플리케이션 실행에 실패한다.
스키마에는 6개의 메타 테이블과 3개의 시퀀스 테이블이 존재한다.
메타 테이블들을 살펴보겠다.
Job 관련 테이블
BATCH_JOB_INSTANCE
CREATE TABLE BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
)
BATCH_JOB_INSTANCE
테이블에는 Job이 실행될 때 해당 Job 인스턴스의 정보가 저장된다.
JOB_INSTANCE_ID
: 고유하게 식별할 수 있는 기본키VERSION
: 업데이트 될 때마다 1씩 증가JOB_NAME
: Job을 구성할 때 부여하는 Job 이름JOB_KEY
:job_name
과job_Parameter
를 합쳐 해싱한 값을 지정
BATCH_JOB_EXECUTION
CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_INSTANCE_ID BIGINT NOT NULL,
CREATE_TIME DATETIME(6) NOT NULL,
START_TIME DATETIME(6) DEFAULT NULL ,
END_TIME DATETIME(6) DEFAULT NULL ,
STATUS VARCHAR(10) ,
EXIT_CODE VARCHAR(2500) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED DATETIME(6),
JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
)
BATCH_JOB_EXECUTION
테이블에는 Job의 실행 정보가 저장된다.
Job 생성, 시작, 종료 시간 및 실행 상태, 메시지 등을 관리한다.
JOB_EXECUTION_ID
:JobExecution
을 고유하게 식별할 수 있는 기본키로JOB_INSTANCE
와 일대다 관계이다.VERSION
: 업데이트 될 때 마다 1씩 증가JOB_INSTANCE_ID
:JOB_INSTANCE
의 키CREATE_TIME
:Execution
이 생성된 시점을 기록START_TIME
:Execution
이 시작된 시점을 기록END_TIME
:Execution
이 종료된 시점을 기록. Job 실행 도중 오류가 발생해서 Job이 중단된 경우, 값이 저장되지 않을 수 있다.STATUS
: 실행 상태를 저장. [ COMPLETED | FAILED | STOPPED | … ]EXIT_CODE
: 실행 종료 코드 저장 [ COMPLETED | FAILED | … ]EXIT_MESSAGE
:STATUS
가 실패일 경우 실패 원인 등을 저장LAST_UPDATED
: 마지막Execution
시점을 기록
BATCH_JOB_EXECUTION_PARAMS
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
JOB_EXECUTION_ID BIGINT NOT NULL ,
TYPE_CD VARCHAR(6) NOT NULL ,
KEY_NAME VARCHAR(100) NOT NULL ,
STRING_VAL VARCHAR(250) ,
DATE_VAL DATETIME(6) DEFAULT NULL ,
LONG_VAL BIGINT ,
DOUBLE_VAL DOUBLE PRECISION ,
IDENTIFYING CHAR(1) NOT NULL ,
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
)
BATCH_JOB_EXECUTION_PARAMS
테이블은 Job과 함께 실행되는 Job의 Parameter 정보들을 저장한다.
JOB_EXECUTION_ID
:JobExecution
식별키 값.JOB_EXECUTION
과 일대다 관계TYPE_CD
:STRING
,LONG
,DATE
,DOUBLE
등 타입 정보KEY_NAME
: 파라미터 키 값STRING_VAL
: 파라미터 문자 값DATE_VAL
: 파라미터 날짜 값LONG_VAL
: 파라미터LONG
값DOUBLE_VAL
: 파라미터DOUBLE
값IDENTIFYING
: 식별여부 (true
|false
)
BATCH_JOB_EXECUTION_CONTEXT
CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT TEXT ,
constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
)
BATCH_JOB_EXECUTION_CONTEXT
테이블은 Job의 실행동안 여러가지 상태정보, 공유 데이터를 직렬화하여 저장해둔다.
Step 간에 서로 데이터를 공유할 수 있다.
JOB_EXECUTION_ID
:JobExecution
식별키,JOB_EXECUTION
마다 각각 생성SHORT_CONTEXT
: Job의 실행 상태 정보, 공유 데이터 등의 정보를 문자열로 저장SERIALIZED_CONTEXT
: 직렬화된 전체 컨텍스트
Step 관련 테이블
BATCH_STEP_EXECUTION
CREATE TABLE BATCH_STEP_EXECUTION (
STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT NOT NULL,
STEP_NAME VARCHAR(100) NOT NULL,
JOB_EXECUTION_ID BIGINT NOT NULL,
START_TIME DATETIME(6) NOT NULL ,
END_TIME DATETIME(6) DEFAULT NULL ,
STATUS VARCHAR(10) ,
COMMIT_COUNT BIGINT ,
READ_COUNT BIGINT ,
FILTER_COUNT BIGINT ,
WRITE_COUNT BIGINT ,
READ_SKIP_COUNT BIGINT ,
WRITE_SKIP_COUNT BIGINT ,
PROCESS_SKIP_COUNT BIGINT ,
ROLLBACK_COUNT BIGINT ,
EXIT_CODE VARCHAR(2500) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED DATETIME(6),
constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
)
BATCH_STEP_EXECUTION
테이블은 Step의 실행 정보가 저장되며 Step 생성, 시작, 종료 시간 및 실행 상태, 메시지 등을 관리한다.
STEP_EXECUTION_ID
: Step의 실행 정보를 고유하게 식별할 수 있는 기본키VERSION
: 업데이트 될 때마다 1씩 증가STEP_NAME
: Step을 구성할 때 부여하는 이름JOB_EXECUTION_ID
:JobExecution
기본키.JOB_EXECUTION
과 일대다 관계START_TIME
:Execution
이 시작된 시점을 기록END_TIME
:Execution
이 종료된 시점을 기록STATUS
: 실행 상태를 저장COMMIT_COUNT
: 트랜잭션 당 커밋되는 수를 기록READ_COUNT
: 실행 시점에Read
한Item
수를 기록FILTER_COUNT
: 실행도중 필터링된Item
수를 기록WRITE_COUNT
: 실행도중 저장되고 커밋된Item
수를 기록READ_SKIP_COUNT
: 실행도중Read
가Skip
된Item
수를 기록WRITE_SKIP_COUNT
: 실행도중Write
가Skip
된Item
수를 기록PROCESS_SKIP_COUNT
: 실행도중Process
가Skip
된Item
수를 기록ROLLBACK_COUNT
: 실행도중Rollback
이 일어난 수를 기록EXIT_CODE
: 실행 종료 코드를 저장EXIT_MESSAGE
:STATUS
가 실패일 경우 실패 원인 등의 내용을 저장LAST_UPDATED
: 마지막 실행 시점을 기록
BATCH_STEP_EXECUTION_CONTEXT
CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT (
STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT TEXT ,
constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
)
BATCH_STEP_EXECUTION_CONTEXT
테이블은 Step의 실행동안 여러가지 상태 정보, 공유 데이터를 직렬화하여 저장해둔다.
Step 별로 저장되며 서로 다른 Step 간에 서로 공유할 수 없다.
STEP_EXECUTION_ID
:StepExecution
식별키 값,STEP_EXECUTION
마다 각각 생성SHORT_CONTEXT
: Step의 실행 상태 정보, 공유 데이터 등의 정보를 문자열로 저장SERIALIZED_CONTEXT
: 직렬화된 전체 컨텍스트
스프링 배치 도메인 이해
Job
Job
은 배치 계층 구조에서 가장 상위에 있는 개념으로 하나의 배치 작업 자체를 의미한다.Job Configuration
을 통해 생성되는 객체 단위로서 배치 작업을 어떻게 구성하고 실행할 것인지 전체적으로 설정하고 명세해 놓은 객체이다.
여러 Step
을 포함하고 있는 컨테이너로서 반드시 한개 이상의 Step
으로 구성해야 한다.
스프링 배치는 Job
인터페이스에 대한 여러 기본 구현체를 제공한다.
대표적으로 SimpleJob
과 FlowJob
이 있다.
SimpleJob
은 순차적으로 Step
을 실행시키는 Job
이다.
모든 Job
에서 유용하게 사용할 수 있는 표준 기능을 갖고 있다.
FlowJob
은 특정한 조건과 흐름에 따라 Step
을 구성하여 실행시키는 Job
이다.Flow
객체를 실행시켜서 작업을 진행한다.
JobInstance
JobInstance
는 Job
이 실행될 때 생성되는 Job
의 논리적 실행 단위로서 고유하게 식별 가능한 작업의 실행을 나타낸다.Job
의 설정과 구성은 동일하지만, Job
이 실행되는 시점에 처리하는 내용은 다르기 때문에 Job
의 실행을 구분해야 한다.
JobInstance
는 Job
과 JobParameters
로 존재 여부를 판단한다.Job
의 이름과 JobParameters
의 해시값인 JobKey
로 BATCH_JOB_INSTANCE
테이블을 조회하여 동일한 데이터가 없다면 새로운 JobInstance
를 생성하고, 이미 데이터가 존재한다면 해당 데이터를 통해 기존 JobInstance
를 만들어 반환한다.
JobParameter
JobParameter
는 Job
을 실행할 때 함께 포함되어 사용되는 파라미터를 가진 도메인 객체를 말하며 하나의 Job
에 존재할 수 있는 여러개의 JobInstance
를 구분하기 위한 용도로 사용된다.
JobParameter
는 JobParameterBuilder
와 DefaultJobParametersConverter
를 통해 코드로 직접 생성하여 전달할 수도 있고, 애플리케이션 실행시에 주입시켜 줄 수도 있다.
JobParameterBuilder
사용
스프링 배치의 Job
을 수동으로 실행하도록 설정하고 JobParamterBuilder
를 통해 JobParameters
를 생성하고 Job
에 전달한다.
application.yml
에 다음과 같이 작성하여 Job
을 수동으로 실행할 수 있도록 한다.
spring:
batch:
job:
enabled: false # 스프링 배치 자동 실행 off
스프링 배치 Job
구성 설정에서 등록한 Job
을 의존 주입받아 JobLauncher
를 통해 실행한다.
이때, JobParametersBuilder
를 통해서 JobParameters
를 생성하고 이를 JobLaucher
에 함께 전달하여 사용한다.
@Component
public class JobRunner implements ApplicationRunner {
@Autowired
private JobLauncher jobLauncher;
@Autowired
private Job job;
@Override
public void run(ApplicationArguments args) throws Exception {
// JobParameters 생성
JobParameters jobParameters = new JobParametersBuilder()
.addString("name", "user2")
.toJobParameters();
// JobLauncher를 통한 Job 수동 실행
jobLauncher.run(job, jobParameters);
}
}
동일한 Job
에 동일한 파라미터로 실행한 정보가 저장되어 있으면 다음과 같은 예외를 반환하며 Job
을 실행하지 않는다.
애플리케이션 실행 시점에 주입
다음과 같이 애플리케이션 실행 시점에 파라미터 정보를 주입해서 사용할 수도 있다.
$ java -jar spring-batch-0.0.1-SNAPSHOT.jar --spring.profiles.active=mysql name=user3
long
, double
등의 타입 정보도 함께 전달해주려면 다음과 같이 작성할 수 있다.
$ java -jar spring-batch-0.0.1-SNAPSHOT.jar --spring.profiles.active=mysql name=user3 seq(long)=3L date(date)=2022/01/01 age(double)=26.9
참고 : zsh 오류
zsh에서 다음과 같이 입력하면 no matches found 오류가 발생한다.
$ java -jar spring-batch-0.0.1-SNAPSHOT.jar --spring.profiles.active=mysql name=user3 seq(long)=3L date(date)=2022/01/01 age(double)=26.9
> zsh: no matches found: seq(long)=3L
아래와 같이 작성하여 해결할 수 있다.
$ java -jar spring-batch-0.0.1-SNAPSHOT.jar --spring.profiles.active=mysql name=user3 'seq(long)=3L' 'date(date)=2022/01/01' 'age(double)=26.9'
참고 : 인텔리제이 애플리케이션 실행 시점 주입 방법
다음과 같이 설정하여 파라미터 값을 전달해줄 수 있다.
JobExecution
JobExecution
은 JobInstance
에 대한 한 번의 시도를 의미하는 객체로서 Job
실행중에 발생한 정보들을 저장하고 있는 객체이다.JobExecution
은 시작 시간, 종료 시간, 상태(시작됨, 완료, 실패), 종료 상태의 속성을 가진다.
JobExecution
은 FAILED
, COMPLETED
등의 Job
실행 결과 상태를 가지고 있다(BATCH_JOB_EXECUTION.STATUS
필드).JobExecution
의 실행 상태 결과가 FAILED
이면 JobInstance
실행이 완료되지 않은 것으로 간주하여 재실행이 가능하다.
하지만 JobExecution
실행 상태 결과가 COMPLETED
이면 실행이 완료된 것으로 간주하여 재실행이 불가능하다.
따라서 실행 상태 결과가 COMPLETED
가 될 때 까지 하나의 JobInstance
내에서 여러번의 시도가 생길 수 있다.
아래는 JobExecution
객체의 생성 흐름을 나타낸 것이다.
Step
Step
은 Batch Job을 구성하는 독립적인 하나의 단계로서 실제 패치 처리를 정의하고 컨트롤하는데 필요한 모든 정보를 가지고 있는 도메인 객체이다.
단순한 단일 태스크 뿐만 아니라 입력과 처리, 출력과 관련된 복잡한 비즈니스 로직을 포함하는 모든 설정들을 담고 있다.Step
은 배치 작업을 어떻게 구성하고 실행할 것인지를 명세한 Job
의 세부 작업을 Task
기반으로 설정하고 명세해 놓은 객체이다.
스프링 배치는 Step
인터페이스에 대한 여러 기본 구현체를 제공한다.TaskletStep
, PartitionStep
, JobStep
, FlowStep
등이 있다.
TaskletStep
은 가장 기본이 되는 클래스로서 Tasklet
타입의 구현체들을 제어한다.PartitionStep
은 멀티 스레드 방식으로 Step
을 여러 개로 분리해서 실행한다.JobStep
은 Step
내에서 Job
을 실행하도록 한다.FlowStep
은 Step
내에서 Flow
를 실행하도록 한다.
StepExecution
StepExecution
은 Step
에 대한 한 번의 시도를 의미하는 객체이다.Step
실행중에 발생한 정보들을 저장하고 있다.Step
이 매번 시도될 때마다 생성되며 각 Step
별로 생성된다.Job
이 재시작 하더라도 이미 성공적으로 완료된 Step
은 재실행되지 않고 실패한 Step
만 실행된다.
만약 이전 단계의 Step
이 실패해서 현재 Step
을 실행하지 않았다면 현재 Step
의 StepExecution
은 생성되지 않는다.Step
이 실제로 시작되었을 때만 StepExecution
을 생성한다.
StepContribution
StepContribution
은 청크 프로세스의 변경 사항을 버퍼링 한 후, StepExecution
상태를 업데이트하는 도메인 객체이다.
청크 커밋 직전에 StepExecution
의 apply
메서드를 호출하여 상태를 업데이트 한다.
일반적으로 StepExecution
은 BatchStatus
와 ExitStatus
를 갖는다.StepContribution
은 StepExecution
의 ExitStatus
값을 변경할 수 있는 기능을 갖는다.ExitStatus
의 기본 종료 코드 외에 사용자 정의 종료 코드를 생성해서 적용할 수 있다.
아래는 StepContribution
의 생성부터 청크 프로세스의 변경 사항을 StepExecution
에 업데이트하는 과정을 나타낸 도식이다.
ExecutionContext
ExecutionContext
는 프레임워크에서 유지 및 관리하는 키/값으로 된 컬렉션으로, StepExecution
또는 JobExecution
객체의 상태를 저장하는 공유 객체이다.ExecutionContext
가 데이터베이스에 저장될 때 Json 형태로 직렬화 한 값으로 저장된다.
ExecutionContext
가 공유되는 범위는 다음과 같다.
Step
범위 : 각Step
의StepExecution
에 저장되며Step
간 서로 공유되지 않는다.Job
범위 : 각Job
의JobExecution
에 저장되며Job
간 서로 공유되지 않으나 해당Job
의Step
간에는 서로 공유가 가능하다.
ExecutionContext
은 Job
재시작시 이미 처리한 데이터는 건너뛰고 이후로 수행하도록 할 때 상태 정보를 활용한다.
Job
이 실패하여 재실행 될 때,JobExecutionContext
를 처음부터 새로 생성하는 것이 아니라 데이터베이스에 저장된JobExecutionContext
를 바탕으로 재생성하여 사용한다.
따라서Job
실패 직전에JobExecutionContext
에 담아둔 데이터가 있다면, 해당Job
을 재수행하면 이전Job
에서 담아둔 데이터를 꺼내어 사용할 수 있다.
JobRepository
JobRepository
는 배치 작업 중의 정보를 저장하는 저장소 역할을 한다.Job
이 언제 수행되었고, 언제 끝났는지, 몇 번 실행되었고 실행에 대한 결과 등의 배치 작업의 수행과 관련된 모든 메타 데이터를 저장한다.
JobRepository
는 @EnableBatchProcessing
어노테이션을 선언하면 자동으로 빈으로 생성된다.JobRepository
를 커스터마이징 하려면 BatchConfigurer
인터페이스를 구현하거나 BasicBatchConfigurer
를 상속하면 된다.
JobRepository
커스터마이징을 통해 트랜잭션 격리 수준 설정, 메타 데이터 테이블의 Prefix 변경 등과 같은 설정을 할 수 있다.
JobLaucher
JobLaucher
는 배치 Job
을 실행시키는 역할을 한다.JobLaucner.run()
메서드는 Job
과 JobParameters
를 인자로 받으며 요청된 배치 작업을 수행한 후 클라이언트에게 JobExecution
을 반환한다.
JobLaucher
를 통한 Job
의 실행은 동기적, 비동기적으로 실행되도록 설정할 수 있다.
Job
이 동기적으로 실행되도록 하려면 JobLaucher
의 taskExecutor
를 SyncTaskExecutor
로 설정한다(이는 기본값이 SyncTaskExecutor
이다).Job
이 동기적으로 실행되면 JobLauncher
는 JobExecution
을 획득하고 배치 처리를 최종적으로 완료한 이후 클라이언트에게 JobExecution
을 반환한다.
Job
이 비동기적으로 실행되도록 하려면 JobLauncher
의 taskExecutor
를 SimpleAsyncTaskExecutor
로 설정한다.
비동기적으로 실행되면 JobLaucher
는 JobExecution
을 획득한 이후 클라이언트에게 바로 JobExecution
을 반환하고, 이후 배치 처리를 완료한다.
기본적으로 스프링 배치에서는
JobLauncherApplicationRunner
가 자동적으로JobLauncher
를 실행시킨다.
따라서 배치 어플리케이션 실행시,JobLauncherApplicationRunner
에 의해 자동으로Job
이 실행된다.spring.batch.job.enabled=false
옵션을 주어 자동적으로 실행하지 않도록 설정해야Job
의 실행을 직접 컨트롤 할 수 있다.
'framework > spring-batch' 카테고리의 다른 글
[Spring Batch] Job 관련 내용 정리 (0) | 2022.12.19 |
---|
소중한 공감 감사합니다