공식문서
https://docs.spring.io/spring-batch/docs/current/reference/html/
요약
1. Job을 구현하기 위한 2가지 방법 - tasklet , chunks
1-1) tasklet
- 한가지 일을하는 여러개의 step으로 구성 -> step은 Tasklet 인터페이스를 구현 해야함
- step간의 전송되는 데이터 객체는 직렬화가능해야함 (serializable)
- StepExecutionListner를 구현한 afterStep의 stepExecution에서 객체 담아서 사용 가능
1-2) chunck
- 전체 읽기 한 번, 전체 처리 1번, 전체 입력 1번이 아니라
100개(chunk 단위)로 읽고, 처리, 입력하고, 100개 읽고, 처리, 입력하는 것을 반복한다.
- 하나의 tasklet만 수행하는 하나의 step만 존재 ( 해당 스텝 내에서 reader, processor, writer 등록 )
- 커밋 간격은 한 청크에서 처리할 데이터의 양을 나타냄
- ItemReader, ItemProcessor, ItemWriter 인터페이스를 구현해야함
<Tasklet 보다는 Chunk 방식을 많이 씀> [출처] https://prodo-developer.tistory.com/164
Tasklet로는 단순하게 처리할 수 있는 장점이 있으나, 대 용량을 감당하기엔 부하를 감당할 수 없습니다.
따라서 Chunk를 통해 쪼개서 넣을 필요가 있는데, Tasklet로도 쪼개서 넣을 수 있지만, 가독성에서
떨어지기 때문에 권장하지 않습니다.
현재 사용하고 있는 실무에서도 대용량은 Chunk를 적극 사용하고 있다.
그렇다면 Tasklet 방식과 Chunk 방식에 대해 알아보자.
● Tasklet을 사용한 Task 기반 처리
- 배치 처리 과정이 비교적 쉬운 경우 쉽게 사용
- 대량 처리를 하는 경우 더 복잡
- 하나의 큰 덩어리를 여러 덩어리로 나누어 처리하기 부적합
● Chunk를 사용한 chunk(덩어리) 기반 처리
- ItemReader, ItemProcessor, ItemWriter의 관계 이해 필요
- 대량 처리를 하는 경우 Tasklet 보다 비교적 쉽게 구현
- 예를 들면 10,000개의 데이터 중 1,000개씩 10개의 덩어리로 수행
■ 이를 Tasklet으로 처리하면 10,000개를 한번에 처리하거나, 수동으로 1,000개씩 분할
용어 정리
Job
- Job은 배치 처리 과정을 하나의 단위로 만들어 포현한 객체입니다. 또한 전체 배치 처리에 있어 항상 최상단 계층에 있습니다.
- 위에서 하나의 Job(일감) 안에는 여러 Step(단계)이 있다고 설명했던 바와 같이 스프링 배치에서 Job 객체는 여러 Step 인스턴스를 포함하는 컨테이너 입니다
- Step들의 컨테이너, Step들의 단계 혹은 재시작 가능성과 같은 모든 단계에 대한 전역 속성을 구성합니다.
- 실행시킬 작업. 논리적인 Job 실행의 개념.
Step
- Step은 Job 내부에 구성되어 실제 Batch 작업 수행을 위해 작업을 정의하고 제어, Job을 처리하는 실질적인 단위
- Step은 Job의 독립적이고 순차적인 단계를 캡슐화하는 도메인 객체
- 모든 Job에는 1개 이상의 Step이 있어야 합니다.
- Step의 내용은 전적으로 개발자의 선택에 따라 구성됨.
stepExcution
- status :StepExecution의 상태를 보여주는 지표 ( STARTED/ FAILED/ COMPLETED )
- startTime Step이 시작된 시간
- endTime Step이 종료된 시간
- exitStatus Step의 실행 결과를 보여주는 상태 값
- readCount 성공적으로 읽은 데이터의 개수
- writeCount 성공적으로 쓴 데이터의 개수
- commitCount StepExecution 동안 Commit된 횟수
- rollbackCount StepExecution동안 Rollback된 횟수
- readSkipCount 데이터 읽기 도중 실패로 인하여 skip한 횟수
- processSkipCount 데이터 처리 도중 실패로 인하여 skip한 횟수
- filterCount ItemProcessor에서 Filtering한 데이터의 개수
- writeSkipCount 데이터 쓰기 도중 실패로 인하여 skip한 횟수
JobRepository
- JobRepository는 배치 처리 정보를 담고 있는 매커니즘입니다. 어떤 Job이 실행되었으면 몇 번 실행되었고 언제 끝났는지 등 배치 처리에 대한 메타데이터를 저장합니다.
- 현재 실행 중인 프로세스의 meta data를 저장합니다. : Job이 수행, 종료, 실행 횟수 및 결과 등, Batch수행과 관련된 모든 Meta Data가 저장되어 있음
- JobRepository은 수행되는 Job에 대한 정보를 담고 있는 저장소로 JobExecution과 StepExecution에 대한 CRUD 기능 수행
- Batch 작업 최초 실행 시 JobRepository에서 JobExecution이 생성되고 Batch작업이 실행되는 동안 StepExecution 및 JobExecution의 정보들이 JobRepository에 저장되고 갱신됨
JobLauncher
- JobLauncher는 Job. JobParamerters와 함께 배치를 실행하는 인터페이스입니다.
- Client로부터 요청을 받아 Job을 실행하는 객체입니다.
- JobLauncher는 Batch Job을 실행시키는 역할 수행. Job과 Parameter를 받아서 실행하며 JobExecution를 반환.
- JobLauncher는 taskExecutor 설정을 통해 Job을 동기적 혹은 비동기적으로 실행 가능. – 별도로 설정하지 않으면 syncTaskExecutor클래스가 Dafault로 설정됨
JobRunner
- 외부 실행 모듈과 JobLauncher를 연결해주는 모듈
JobParameter
- Batch Job을 실행하는데 사용하는 파라미터의 집합으로 Job이 실행되는 동안에 Job을 식별하거나 Job에서 참 조하는 데이터로 사용
JobInstance
- 논리적인 Job 실행 (JobInstance=Job+JobParameter)
- 동일한 Job이 각기 다른 JobParameter를 통해 실행된 Job의 실행 단위임
JobExcution
- JobExcution은 한번의 Job 시도를 의미
JobParameters
- JobParameters는 하나의 Job에 존재할 수 있는 여러개의 JobInstance를 구별하기 위한 Parameter 집합임.
Job이 실행되는 동안에 Job을 식별하거나 Job에서 참조하는 데이터로 사용됨.
Job Parameter를 통해 여러 JobInstance 생성 가능
Item
- 처리할 데이터의 가장 작은 구성 요소. ex) 파일의 한 줄, DB의 한 Row, xml의 특정 Element
ItemReader
- Step 안에서 File 또는 DB 등에서 Item을 읽어들임,
- 더 이상 읽어올 item이 없을 때는 read() 메소드에서 null 값을 반환하며 그 전까지는 순차적인 값을 리턴
ItemWriter
- Step 안에서 File 또는 DB 등으로 Item을 저장
Item Processor
- Item Reader에서 읽어 들인 Item에 대하여 필요한 로직처리 작업을 수행
Flow
JobExeplorer와 JobOperator를 통해 JobRepository에 접근할 수 있게 되면서 배치 작업을 수행하는 도중에도 Meta Data를 조회하거나 실행 중인 Job을 멈추게 할 수도 있다.
Chunk oriented processing
스프링 배치 1.x에서는 한 개의 Data를 의미하는 Item을 기반으로 작업을 처리한다. <그림 10>에서와 같이 Item 기반의 처리는 Item을 읽고 처리하고 쓰는 것이 하나의 단위였다면, Chunk 기반의 처리는 지정한 크기만큼 Item을 읽고 처리한 후 이 결과를 list의 형태로 가지고 있다가 한 번에 쓰는 방식인 것이다. 이로 인해 리소스 관리 측면에서 이점을 가져올 수 있게 되었다.
Tasklet
태스크릿은 단계 내에서 단일 태스크를 수행하기 위한 것. 우리의 임무는 차례대로 실행되는 여러 단계로 구성됩니다. 각 단계는 하나의 정의 된 작업만 수행해야합니다.
청크 지향 프로세싱
청크 지향 프로세싱은 트랜잭션 경계 내에서 청크 단위로 데이터를 읽고 생성하는 프로그래밍 기법입니다. 청크란 아이템이 트랜잭션에 커밋되는 수를 말합니다. read한 데이터 수가 지정한 청크 단위와 칠치하면 write를 수행하고 트랜잭션을 커밋합니다. Step 설정에서 chunk()로 커밋 단위를 지정했던 부분
청크 지향프러그래밍의 이점은 1000개 개의 데이터에 대해 배치 로직을 실행한다고 가정했을 때 청크로 나누지 않았을 때는 하나만 실패해도 다른 성공한 999개의 데이터가 롤백됩니다. 그런데 청크 단위를 10으로 해서 배치처리를 하면 도중에 배치 처리에 실패하더라도 다른 청크는 영향을 받지 않습니다. 이러한 이유로 스프링 배치에 정크 단위로 프로그래밍을 지향합니다.
Step을 tasklet 방법으로 구성하느냐, ItemReader, ItemProcessor, ItemWriter의 단위로 구성하느냐에 따라 tasklet 방식이 될 수 있고, 청크 제향 프로세싱 방법이 될 수 있습니다.
metadata table script
spring-batch-core.jar의 schema-*.sql
Commit & Transaction
transaction 프로세스 :
https://terasoluna-batch.github.io/guideline/5.0.0.RELEASE/en/Ch05_Transaction.html
https://studyoverflow.tistory.com/entry/1-Transactions-in-Spring-Batch-The-Basics
https://godekdls.github.io/Spring%20Batch/configuringastep/#518-transaction-attributes
Spring Batch Scope
@StepScope, @JobScope
Job Parameter
Spring Batch의 경우 외부 혹은 내부에서 파라미터를 받아 여러 Batch 컴포넌트에서 사용할 수 있게 지원하고 있습니다.
이 파라미터를 Job Parameter라고 합니다.
Job Parameter를 사용하기 위해선 항상 Spring Batch 전용 Scope를 선언해야만 하는데요.
크게 @StepScope와 @JobScope 2가지가 있습니다.
@StepScope : Step 실행 시점에 Spring Bean으로 생성
@JobScope : Job 실행 시점에 Spring Bean으로 생성, Bean의 생성 시점을 지정된 Scope가 실행되는 시점으로 지연시킴.
Spring JobParameter Vs 시스템 변수
시스템 변수는 application.properties와 -D 옵션으로 실행하는 변수까지 포함
- JobParameter 사용 방법
@Value("#{jobParameters[requestDate]}"
- 시스템변수 사용 방법
@Autowired
private JobProperties jobProperties;
https://velog.io/@lxxjn0/Spring-Batch-Guide-05.-Spring-Batch-Scope-Job-Parameter
- Spring Batch 프로젝트는 Accenture와 Spring Source의 공동 작업으로 2007년에 탄생.
( Accenture의 배치 노하우 & 기술력과 Spring 프레임워크가 합쳐져 만들어진 것이 Spring Batch )
Spring Batch는 Spring의 특성을 그대로 가져왔습니다.
그래서 DI, AOP, 서비스 추상화 등 Spring 프레임워크의 3대 요소를 모두 사용할 수 있으면서, Accenture의 Batch 노하우가 담긴 아키텍처를 사용할 수 있음.
Spring Boot Batch 2.0은 최신버전(2018.03 기준)인 스프링 배치 4.0 기반
→ 자바8 이상에서 동작
→ 스프링 프레임워크 5로 진화하며 새롭게 재배열된 의존성 트리 지원
→ ItemReaders, ItemProcesors, ItemWriters에 대한 빌더 제공
→ 지원하는 Reader & Writer
. Spring Batch 정보
- Spring Batch란 대용량의 레코드를 처리하기 위한 Spring Framework 하위 프레임워크다.
- 로깅 및 추적, 트랜잭션관리, 작업 처리 현황, 작업 재시작, 작업 무시, 자원 관리가 가능하다.
- 현재 JVM에서 동작하는 배치 프로세스를 위한 산업 표준
- 기본 개념
자세한 Job , Step 구성도
- 데이터를 읽을 때 너무많은 데이터가 있을경우 메모리가 가득 찰 수 있으므로 ItemReader는 지정된 Chunk 사이즈만큼 읽고
ItemWriter는 Chunk 사이즈만큼 저장할 수있는 기능이 있다. - Step 구성 시 ItemReader, ItemWriter, ItemProcessor를 사용하기 싫으면 나만의 custom 구현을 tasklet을 사용하여 구현이 가능하다.
2.Scheduling
- 배치를 구성 후 이를 주기적으로 실행 할 Scheduler가 필요하다.
- 단순한경우 cron을 사용하거나, JDK의 ScheduleExecutorServie 가 사용가능하다.
- 좀더 상위의 추상화가 필요한 경우 java.util.concurrent.Executor 인스턴스를 위임한 스프링의 @Scheduled 어노테이션을 사용할 수 있으며
현재 배치구성은 @Scheduled를 사용중이다. - 만약 클러스터링 개념을 넣으려면 이벤트주도 방식을 이용한 Spring integration을 사용하면된다.(원격 분산 병렬 처리)
스프링 부트 배치 주의사항
스프링 부트 배치는 스프링 배치를 간편하게 사용 할 수 있게 래핑한 프로젝트입니다. 따라서 스프링 부트 배치와 스프링 배치에 모두에서 다음과 같은 주의사항을 염두해야 합니다.
- 가능하면 단순화해서 복잡한 구조와 로직을 피해야합니다.
- 데이터를 직접 사용하는 편이 빈번하게 일어나므로 데이터 무결성을 우지하는데 유효성 검사 등의 방어책이 있어야합니다.
- 배치 처리 시스템 I/O 사용을 최소화해야합니다. 잦은 I/O로 데이터베이스 컨넥션과 네트워크 비용이 커지면 성능에 영향을 줄 수 있기 때문입니다. 따라서 가능하면 한번에 데이터를 조회하여 메모리에 저장해두고 처리를 한 다음. 그결과를 한번에 데이터베이스에 저장하는것이 좋습니다.
- 일반적으로 같은 서비스에 사용되는 웹 API, 배치, 기타 프로젝트들을 서로 영향을 줍니다. 따라서 배치 처리가 진행되는 동안 다른 프로젝트 요소에 영향을 주는 경우가 없는지 주의를 기울여야합니다.
- 스프링 부트는 배치 스케쥴러를 제공하지 않습니다. 따라서 배치 처리 기능만 제공하여 스케쥴링 기능은 스프링에서 제공하는 쿼치 프레임워크 등을 이용해야합니다. 리눅스 crontab 명령은 가장 간단히 사용 할 수 있지만 이는 추천하지 않습니다. crontab의 경우 각 서버마다 따로 스케쥴러를 관리해야 하며 무엇보다 클러스터링 기능이 제공되지 않습니다. 반면에 쿼츠 같은 스케쥴링은 프레임워크를 사용한다면 클러스터링뿐만 아니라 다양한 스케쥴링 기능, 실행 이력 관리 등 여러 이점을 얻을 수 있습니다.
배치 기본 개념 등등에 대한 참고
1. www.baeldung.com/spring-batch-tasklet-chunk
2. woowabros.github.io/experience/2018/05/26/woowahan-juso.html
3. cheese10yun.github.io/spring-batch-basic/
7. www.toptal.com/spring/spring-batch-tutorial
Test Code
Chunk vs Tasklet
1. https://sejoung.github.io/2018/07/2018-07-09-Chunk_and_Tasklet/
2. https://prodo-developer.tistory.com/164
////////////
commit transaction 단위
'Spring MVC' 카테고리의 다른 글
Spring Boot Upgrade 2.0.x -> 2.7.2 (0) | 2022.07.27 |
---|---|
MyBatis Package 경로 줄이기 (0) | 2022.05.19 |
Spring Batch (0) | 2019.01.18 |
Spring Transaction 관련 (0) | 2016.11.30 |
Spring Annotation 정리 (0) | 2016.10.07 |