Spring Batch

lgw2236·2023년 1월 3일
0

개발기록

목록 보기
3/8

작년에 도메인 정산쪽 배치 프로세스를 개발면서 고생을 좀 했었는데
batch와 Scheduler는 정리를 해야지 해야지 하면서
귀차니즘이 발동해 안하고있었다...
올해 사이드프로젝트에 spring batch를 쓸일이 생길 것같아 .. 이번 기회에 한번 정리해보자..!

spring batch란?

Spring Batch는 엔터프라이즈 시스템의 운영에 있어 대용량 일괄처리의 편의를 위해 설계된 가볍고 포괄적인 배치 프레임워크다. Spring batch 라는 이름 그대로 spring의 특성을 그대로 가져왔기 때문에 DI, AOP, 서비스 추상화 등 Spring 프레임워크의 3대 요소를 모두 사용할 수 있다.

spring batch 구성 요소

Job

Job은 배치처리 과정을 하나의 단위로 만들어 놓은 객체입니다. 또한 배치처리 과정에 있어 전체 계층 최상단에 위치하고 있습니다.

JobInstance

JobInstance는 Job의 실행의 단위를 나타냅니다. Job을 실행시키게 되면 하나의 JobInstance가 생성되게 됩니다. 예를들어 1월 1일 실행, 1월 2일 실행을 하게 되면 각각의 JobInstance가 생성되며 1월 1일 실행한 JobInstance가 실패하여 다시 실행을 시키더라도 이 JobInstance는 1월 1일에 대한 데이터만 처리하게 됩니다.

JobParameters

JobInstance는 Job의 실행 단위라고 했습니다. 그렇다면 JonInstance는 어떻게구별 할까요? 이는 바로 JobParameters 객체로 구분하게 됩니다. JobParameters는 JobInstance 구별 외에도 개발자 JobInstacne에 전달되는 매개변수 역할도 하고 있습니다.

또한 JobParameters는 String, Double, Long, Date 4가지 형식만을 지원하고 있습니다.

JobExecution

JobExecution은 JobInstance에 대한 실행 시도에 대한 객체입니다. 1월 1일에 실행한 JobInstacne가 실패하여 재실행을 하여도 동일한 JobInstance를 실행시키지만 이 2번에 실행에 대한 JobExecution은 개별로 생기게 됩니다. JobExecution는 이러한 JobInstance 실행에 대한 상태,시작시간, 종료시간, 생성시간 등의 정보를 담고 있습니다.

Step

Step은 Job의 배치처리를 정의하고 순차적인 단계를 캡슐화 합니다. Job은 최소한 1개 이상의 Step을 가져야 하며 Job의 실제 일괄 처리를 제어하는 모든 정보가 들어있습니다.
Step에는 Tasklet, Chunk 기반으로 2가지가 있다.

Tasklet
Step이 중지될 때까지 execute 메서드가 계속 반복해서 수행하고 수행할 때마다 독립적인 트랜잭션이 얻어진다. 초기화, 저장 프로시저 실행, 알림 전송과 같은 잡에서 일반적으로 사용된다.

Chunk
한 번에 하나씩 데이터(row)를 읽어 Chunk라는 덩어리를 만든 뒤, Chunk 단위로 트랜잭션을 다루는 것
Chunk 단위로 트랜잭션을 수행하기 때문에 실패할 경우엔 해당 Chunk 만큼만 롤백이 되고, 이전에 커밋된 트랜잭션 범위까지는 반영이 된다.
[Chunk 시나리오]
▶읽기(Read) — Database에서 배치처리를 할 Data를 읽어온다
▶처리(Processing) — 읽어온 Data를 가공,처리를 한다 (필수사항X)
▶쓰기(Write) — 가공,처리한 데이터를 Database에 저장한다.

StepExecution

StepExecution은 JobExecution과 동일하게 Step 실행 시도에 대한 객체를 나타냅니다. 하지만 Job이 여러개의 Step으로 구성되어 있을 경우 이전 단계의 Step이 실패하게 되면 다음 단계가 실행되지 않음으로 실패 이후 StepExecution은 생성되지 않습니다. StepExecution 또한 JobExecution과 동일하게 실제 시작이 될 때만 생성됩니다. StepExecution에는 JobExecution에 저장되는 정보 외에 read 수, write 수, commit 수, skip 수 등의 정보들도 저장이 됩니다.

ExecutionContext

ExecutionContext란 Job에서 데이터를 공유 할 수 있는 데이터 저장소입니다. Spring Batch에서 제공하느 ExecutionContext는 JobExecutionContext, StepExecutionContext 2가지 종류가 있으나 이 두가지는 지정되는 범위가 다릅니다. JobExecutionContext의 경우 Commit 시점에 저장되는 반면 StepExecutionContext는 실행 사이에 저장이 되게 됩니다. ExecutionContext를 통해 Step간 Data 공유가 가능하며 Job 실패시 ExecutionContext를 통한 마지막 실행 값을 재구성 할 수 있습니다.

JobRepository

JobRepository는 위에서 말한 모든 배치 처리 정보를 담고있는 매커니즘입니다. Job이 실행되게 되면 JobRepository에 JobExecution과 StepExecution을 생성하게 되며 JobRepository에서 Execution 정보들을 저장하고 조회하며 사용하게 됩니다.

JobLauncher

JobLauncher는 Job과 JobParameters를 사용하여 Job을 실행하는 객체입니다.

ItemReader

ItemReader는 Step에서 Item을 읽어오는 인터페이스입니다. ItemReader에 대한 다양한 인터페이스가 존재하며 다양한 방법으로 Item을 읽어 올 수 있습니다.

ItemWriter

ItemWriter는 처리 된 Data를 Writer 할 때 사용한다. Writer는 처리 결과물에 따라 Insert가 될 수도 Update가 될 수도 Queue를 사용한다면 Send가 될 수도 있다. Writer 또한 Read와 동일하게 다양한 인터페이스가 존재한다. Writer는 기본적으로 Item을 Chunk로 묶어 처리하고 있습니다.

ItemProcessor

Item Processor는 Reader에서 읽어온 Item을 데이터를 처리하는 역할을 하고 있다. Processor는 배치를 처리하는데 필수 요소는 아니며 Reader, Writer, Processor 처리를 분리하여 각각의 역할을 명확하게 구분하고 있습니다.

Spring Batch 동작 프로세스

Spring Batch 예시 코드

package xx.xx.xx.job;

@Deprecated
@Configuration
@ConditionalOnProperty(name = "spring.batch.job.names", havingValue = "exampleJob")
public class exampleJob {
	@Autowired
	private JobBuilderFactory jobBuilderFactory;
	@Autowired
	private StepBuilderFactory stepBuilderFactory;
	@Autowired
	private ExampleService exampleService;
	private Long jobId;

	public exampleJob() {
		log.info("======== exampleJob Job configured!! ==========");
	}
	/* 실행시켜야 하는 Jobname 으로 빈 주입 */
	@Bean(name = "exampleJob")
	public Job exampleJob() {
		return jobBuilderFactory
				.get("exampleJob")
				.start(step())
                .next(step2())
				.incrementer(new RunIdIncrementer())
				.build();
	}
	
	@Bean
	public Step step() {
		return stepBuilderFactory.get("simpleStep1").tasklet((contribution, chunkContext) -> {
			JobExecution jobExecution = chunkContext.getStepContext().getStepExecution().getJobExecution();
			ExecutionContext jobContext = jobExecution.getExecutionContext();
			Long jobId = jobExecution.getJobId();
			String jobName = jobExecution.getJobInstance().getJobName();
			
			/*step1 비즈니스 로직*/
            exampleService.exampleBatch(jobId, jobName);
			return RepeatStatus.FINISHED;

		}).build();
	}
    
    @Bean
	public Step step2() {
		return stepBuilderFactory.get("simpleStep1").tasklet((contribution, chunkContext) -> {
			JobExecution jobExecution = chunkContext.getStepContext().getStepExecution().getJobExecution();
			ExecutionContext jobContext = jobExecution.getExecutionContext();
			Long jobId = jobExecution.getJobId();
			String jobName = jobExecution.getJobInstance().getJobName();
			
			/*step2 비즈니스 로직*/
            exampleService.exampleSecondBatch(jobId, jobName);
			return RepeatStatus.FINISHED;

		}).build();
	}
    
}

Spring Quartz는 batch랑 같은건가?

간혹 사람들이 spring batch 를 접할때 quartz와 혼동하는 경우가 많은데 batch와 quartz는 엄연히 다른 기능을 지원한다.
batch는 대용량 데이터 처리를 quartz는 이러한 batch 작업을 스케쥴링하는 스케쥴러 역할을 지원한다.
고로 batch + quartz를 이용해 자동화 기능을 구현하는 경우가 많다.

Spring Batch DB 테이블 프로세스

[테이블 구성]

1. BATCH_JOB_INSTANCE

BATCH_JOB_INSTANCE 테이블에는 JobInstance에 관련된 모든 정보가 포함되어 있습니다. 또한 해당 Table은 전체 계층 구조의 최상위 역할을 합니다.

2.BATCH_JOB_EXECUTION_PARAMS

BATCH_JOB_EXECUTION_PARAMS 테이블에는 Job을 실행 시킬 때 사용했던 JobParameters에 대한 정보를 저장하고 있습니다.

3.BATCH_JOB_EXECUTION

BATCH_JOB_EXECUTION테이블에는 JobExcution에 관련된 모든 정보를 저장하고 있습니다. JobExcution은 JobInstance가 실행 될 때마다 시작시간, 종료시간, 종료코드 등 다양한 정보를 가지고 있습니다.

4.BATCH_STEP_EXECUTION

BATCH_JOB_EXECUTION테이블에는 StepExecution에 대한 정보를 저장하고 있습니다. BATCH_JOB_EXECUTION 테이블과 여러 면에서 유사하며 STEP을 EXECUTION 정보인 읽은 수, 커밋 수, 스킵 수 등 다양한 정보를 추가로 담고 있습니다.

5.BATCH_JOB_EXECUTION_CONTEXT, BATCH_STEP_EXECUTION_CONTEXT 

BATCH_(JOB,STEP)_EXECUTION_CONTEXT테이블에는 JobExecution과 StepExecution의 ExecutionContext 정보가 들어있습니다.이 ExecutionContext 데이터는 일반적으로 JobInstance가 실패 시 중단된 위치에서 다시 시작할 수 있는 정보를 저장하고 있습니다.

참조문서:https://docs.spring.io/spring-batch/docs/current/reference/html/job.html

profile
어제보다 오늘 더

0개의 댓글