잡이 처리되는데 걸리는 시간, 오류로 인해 재시도된 아이템 수, 잡이 어디까지 실행됐는지 등을 기록하여 모니터링 데이터로 사용할 수 있다.
Job Repository란?
스프링 배치에서 JobRepository는 인터페이스 혹은 메타데이터를 저장하는 저장소를 의미한다. 여기서는 저장소에 대해 알아본다.
스프링배치에서는 관계형 데이터베이스와 인메모리 저장소를 사용할 수 있다.
관계형 데이터베이스 사용하기
스프링 배치가 제공하는 여러 테이블을 사용해 배치 메타데이터를 저장한다.
Spring Batch Metadata Schema
Version
대부분의 메타데이터 테이블에서 VERSION 컬럼을 가지고 있다.
스프링 배치는 데이터베이스에 업데이트를 처리할 때 낙관적 잠금 전략(Optimistic Locking Strategy)을 사용한다. 업데이트가 발생하면 VERSION 컬럼의 값을 1씩 증가시킨다. 만일 읽어왔던 데이터를 업데이트하려는데, 이미 VERSION 값이 달라져 있다면 동시 업데이트가 발생한 것이므로 OptimisticLockingFailureException을 던진다.
BATCH_JOB_INSTANCE
잡을 식별 가능한 파라미터로 실행하면 JobInstance 가 생성된다. 이 테이블의 레코드는 JobInstance를 나타낸다.
잡의 논리적인 실행을 나타낸다.
컬럼
타입
설명
JOB_INSTANCE_ID
BIGINT
PK
VERSION
BIGINT
버전
JOB_NAME
VARCHAR(100)
잡 이름
JOB_KEY
VARCHAR(32)
잡 파라미터들을 직렬화(해시)한 값. 잡 파라미터는 동일한 잡에서 JobInstance를 식별하는데 사용된다.
BATCH_JOB_EXECUTION
잡의 물리적인 실행을 나타낸다. 동일한 파라미터로 잡을 여러 번 실행하면 여러 개의 레코드가 생성된다.
JobInstance(BATCH_JOB_EXECUTION)과는 1:N 관계 이다.
컬럼
타입
설명
JOB_EXECUTION_ID
BIGINT
PK
VERSION
BIGINT
버전
JOB_INSTANCE_ID
BIGINT
BATCH_JOB_INSTANCE 테이블의 PK
CREATE_TIME
DATETIME(6)
execution의 생성 시각
START_TIME
DATETIME(6)
execution의 시작 시각
END_TIME
DATETIME(6)
execution의 종료 시각
STATUS
VARCHAR(10)
execution의 상태
EXIT_CODE
VARCHAR(2500)
execution의 exit code
EXIT_MESSAGE
VARCHAR(2500)
exit에 대한 자세한 메시지. 실패한 경우라면 스택 트레이스.
LAST_UPDATED
DATETIME(6)
최종 갱신 시각
BATCH_JOB_EXECUTION_CONTEXT
JobExecution의 ExecutionContext와 관련된 모든 정보를 저장한다.
JobExecution(BATCH_JOB_EXECUTION)과는 1:1 관계이다.
일반적으로 상태를 저장하며, 실패한 잡을 다시 실행하면 이 데이터를 읽어서 "실패한 곳에서 부터 다시 시작"할 수 있다.
컬럼
타입
설명
JOB_EXECUTION_ID
BIGINT
BATCH_JOB_EXECUTION 테이블의 PK
SHORT_CONTEXT
VARCHAR(2500)
SERIALIZED_CONTEXT의 문자열 버전
SERIALIZED_CONTEXT
TEXT
직렬화(Jackson2)된 전체 context
BATCH_JOB_EXECUTION_PARAMS
잡이 실행될 때 마다 잡 파라미터를 저장한다.
JobExecution(BATCH_JOB_EXECUTION) 과는 1:N 관계이다.
잡을 식별하는데 사용되는 파라미터는 IDENTIFYING 플래그가 Y이다.
테이블은 key-value 정보가 저장되며, 데이터 타입별로 테이블이 분리되어 있지 않고 하나의 테이블에 여러 데이터 타입을 저장할 수 있도록 반정규화(demormalized) 되어 있다.
컬럼
타입
설명
JOB_EXECUTION_ID
BIGINT
BATCH_JOB_EXECUTION의 PK
TYPE_CODE
VARCHAR(6)
저장된 값의 데이터 타입("STRING", "DATE", "LONG", "DOUBLE")
KEY_NAME
VARCHAR(100)
파라미터 이름
STRING_VAL
VARCHAR(250)
타입이 string인 경우의 파라미터 값
DATE_VAL
DATETIME(6)
타입이 date인 경우의 파라미터 값
LONG_VAL
BIGINT
타입이 long인 경우의 파라미터 값
DOUBLE_VAL
DOUBLE
타입이 double인 경우의 파라미터 값
IDENTIFYING
CHAR(1)
파라미터가 JobInstance를 식별하는데 사용되는지 여부
BATCH_STEP_EXECUTION
스텝의 실행을 나타낸다.
스텝의 시작/종료 시각, 상태를 저장한다.
스텝의 실행에 대한 분석을 위한 다양한 횟수(read/process/write/skip/rollbak/...) 값도 저장한다.
컬럼
타입
설명
STEP_EXECUTION_ID
BIGINT
PK
VERSION
BIGINT
버전
STEP_NAME
VARCHAR(100)
스텝 이름
JOB_EXECUTION_ID
BIGINT
BATCH_JOB_EXECUTION 테이블의 PK
START_TIME
DATETIME(6)
execution의 시작 시각
END_TIME
DATETIME(6)
execution의 종료 시각
STATUS
VARCHAR(10)
execution의 상태
COMMIT_COUNT
BIGINT
트랜잭션을 커밋한 횟수
READ_COUNT
BIGINT
읽은 아이템의 수
FILTER_COUNT
BIGINT
필터링(제외된)된 아이템의 수
WRITE_COUNT
BIGINT
기록된 아이템 수
READ_SKIP_COUNT
BIGINT
ItemReader 내에서 예외가 발생해서 건너뛴 아이템 수
PROCESS_SKIP_COUNT
BIGINT
ItemProcessor 내에서 예외가 발생해서 건너뛴 아이템 수
WRITE_SKIP_COUNT
BIGINT
ItemWriter 내에서 예외가 발생해서 건너뛴 아이템 수
ROLLBACK_COUNT
BIGINT
롤백된 트랜잭션 수(retry를 하기 위한 롤백이나 skip을 처리하기 위한 롤백도 포함)
EXIT_CODE
VARCHAR(2500)
execution의 exit code
EXIT_MESSAGE
VARCHAR(2500)
exit에 대한 자세한 메시지. 실패한 경우라면 스택 트레이스.
LAST_UPDATED
DATETIME(6)
최종 갱신 시각
BATCH_STEP_EXECUTION_CONTEXT
StepExecution의 ExecutionContext와 관련된 모든 정보를 저장한다.
StepExecution(BATCH_STEP_EXECUTION)과는 1:1 관계이다.
일반적으로 상태를 저장하며, 실패한 잡을 다시 실행하면 이 데이터를 읽어서 "실패한 곳에서 부터 다시 시작"할 수 있다.
컬럼
타입
설명
STEP_EXECUTION_ID
BIGINT
BATCH_STEP_EXECUTION 테이블의 PK
SHORT_CONTEXT
VARCHAR(2500)
SERIALIZED_CONTEXT의 문자열 버전
SERIALIZED_CONTEXT
TEXT
직렬화(Jackson2)된 전체 context
인메모리 Job Repository
스프링 배치는 개발이나 테스트 환경에서 사용할 수 있는 인메모리 JobRepository를 제공한다.
java.util.Map 객체를 저장소로 사용하는 JobRepository 구현체를 제공한다.
배치 인프라스트럭처 구성하기
@EnableBatchProcessing 애너테이션을 사용하면 대부분의 배치 인프라스트럭처가 자동으로 준비된다.
BatchConfigurer 인터페이스를 사용해서 스프링 배치 인프라스트럭처를 커스터마이징 할 수 있다.
BatchConfigurer 인터페이스
BatchConfigurer 인터페이스는 스프링 배치 인프라스트럭처 컴포넌트의 구성을 커스터마이징하는데 사용되는 전략 인터페이스이다.
@EnableBatchProcessing 애너테이션을 사용하면, SimpleBatchConfiguration에서 인프라스트럭처 컴포넌트들을 생성하여 ApplicationContext에 등록한다. 커스터마이징한 컴포넌트 생성해서 bean으로 등록하고 싶다면 BatchConfigurer를 사용하면 된다.
/**
* Strategy interface for users to provide as a factory for custom components needed by a Batch system.
*/
public interface BatchConfigurer {
JobRepository getJobRepository() throws Exception;
PlatformTransactionManager getTransactionManager() throws Exception;
JobLauncher getJobLauncher() throws Exception;
JobExplorer getJobExplorer() throws Exception;
}
각 메서드는 스프링 배치 인프라스트럭처의 주요 컴포넌트를 제공한다.
PlatformTransactionManager는 프레임워크가 제공하는 모든 트랜잭션 관리에서 사용된다.
JobExplorer는 job repository의 데이터에 읽기 전용으로 접근할 수 있다.
스프링 배치가 제공하는 구현체인 DefaultBatchConfigurer는 모든 컴포넌트에 대한 기본 구현을 제공하므로, 이를 상속해 필요한 메소드만 재정의하면 된다.
오버라이드를 위한 createJobLauncher(), createJobRepository(), createJobExplorer() 메소드를 제공한다.
JobRepository 커스터마이징하기
JobRepository는 JobRepositoryFactoryBean을 통해 생성되며, 이 FactoryBean은 다양한 속성을 커스터마이징 할 수 있는 기능을 제공한다 (p.190 표 5-7)
createJobRepository() 메소드를 재정의해야 하는 가장 일반적인 시나리오는 ApplicationContext에 두 개 이상의 데이터소스가 존재하는 경우이다. 이 경우 JobRepository가 사용하는 데이터소스는 명시적으로 구성해야 한다.
아니면 ChainedTransactionManager+LazyConnectionDataSourceProxy를 사용하여 두 개의 데이터소스를 묶어서 사용할 수 있다. 다음 글들을 참고하자.
TransactionManager를 커스터마이징 하려면 오버라이드용 메서드가 아니라 getTransactionManager():TransactionManager 를 사용하여야 한다.
왜냐하면 DefaultBatchConfigurer는 setDataSource(DataSource) 메서드에서 내부적으로 getTransactionManager()를 호출하여 null인 경우에는 DataSourceTransactionManager를 자동으로 생성하기 때문이다.
그래서 DefaultBatchConfigurer는 오버라이드용 메소드인 createTransactionManager()는 제공하지 않는다.
@Component
public class DefaultBatchConfigurer implements BatchConfigurer {
private PlatformTransactionManager transactionManager;
@Autowired(required = false)
public void setDataSource(DataSource dataSource) {
...
if(getTransactionManager() == null) {
logger.warn("No transaction manager was provided, using a DataSourceTransactionManager");
this.transactionManager = new DataSourceTransactionManager(this.dataSource);
}
}
...
JobExplorer 커스터마이징하기
JobExplorer는 JobRepository가 다루는 데이터에 대한 읽기 전용 뷰이다.
JobRepository를 커스터마이징 했다면, JobExeplorer도 동일하게 커스터마이징 하는게 좋다.
예제와 설명은 p.194~195를 참고하자.
JobLauncher 커스터마이징하기
JobLauncher는 스프링 배치 잡을 실행하는 진입점이다.
스프링 부트는 SimpleJobLauncher를 사용하며, 스프링 부트로 잡을 실행할 때는 커스터마이징할 필요가 없다.
스프링 MVC의 컨트롤러를 통해 잡을 실행하려는 경우 SimpleLauncher의 동작 방식을 조정할 수 있다.
데이터베이스 구성하기
스프링 부트에서 데이터베이스를 사용하려면 데이터베이스 드라이버를 클래스 패스에 추가하고, 적절한 데이터소스 프로퍼티를 구성하면 된다 - spring.datasource.*
스프링 배치의 메타데이터 스키마를 생성하기 위한 스크립트의 실행하도록 지정할 수 있다 - spring.batch.initialize-schema
always: 애플리케이션 실행시 마다 스크립트를 실행. DROP문이 없으며 오류가 발생하면 무시.
never: 스크립트를 실행하지 않음.
embedded (default): 내장 데이터베이스를 사용. 애플리케이션 실행 시마다 데이터가 초기화됨.
댓글