2022. 9. 27. 00:08ㆍspring
Spring Batch 아키텍처
1. 배치 란?
가. 배치(Batch) 프로그램이란?
• 일괄적인 반복 처리작업
• 대부분 I/O에 대한 처리부터 내부적 비즈니스 로직 구현, Logging같은 부가기능까지 모두 개발자가 직접 개발이 필요.
나. 배치(Batch) 프로그램의 특징
• 사용자와의 상호 작용이 없다.
• 정해진 시간 제약 내에 실행이 완료 되어야 한다.
• 많은 자원이 소모되는 대용량 작업이다.
• 테스트가 어렵고, 테스트에 많은 시간이 소요된다.
2. 배치(Batch)시스템에 대한 대표적인 오해 (Pitfalls)
• 배치는 비교적 단순하고 덜 중요하다.
- 배치는 자동화된 대량 처리를 필요로 하는 온라인/정보계/대외계 모두와 밀접한 연관 관계를 갖고 있어 전사시스템이 유기적으로 업무를 처리하는 데 있어 촉매제와 같은 역할을 수행한다. (직접 사용자를 만족시키는 건 적으나, 부지런히 정보가 제때 처리되어야 한다.)
• 배치는 성능이 제일 중요하므로 C 같은 언어로 개발해야 한다
- 배치의 성능 최적화는 프로그래밍 언어나 프로그래밍 기법이 아닌 아키텍처 수준의 최적화를 통해 해결되어야 한다.
- 최적화 기법의 적용순서
* 배치업무 최적화 : 유사 업무 통합, 불필요한 반복 작업 제거
* 관리 고도화 : 수작업 데이터 검증최소화, 잘못된 결과로 재작업 최소화
* I/O 비용 최소화 : 배치 수행 시간의 80% 이상은 I/O 비용이며, I/O를 최소화 해야 최적화 된 성능 향상.
* 프로그램 최적화 : 일정 사이즈로 처리 데이터를 균일하게 Fetch해서 적정 횟수만큼 묶어 Commit. 프로그램 튜닝 팁 적용
3. Spring batch 란?
4. Spring batch 로 가능한 시나리오
5. Spring batch 의 기술적 측면
- 배치가 실행되는 환경과 배치 업무 사이의 관심사를 분리한다.
- 개발자는 비즈니스 로직에 집중하고, 나머지는 프레임워크에서 처리한다.
- 배치 작업의 공통적인 부분을 핵심 인터페이스로 제공한다.(표준화)
- 핵심 인터페이스에 대한 default구현체를 제공해주어 쉽게 이용가능.
- 설정, 커스터마이징, 확장을 쉽게 할 수 있게 해준다.
6. Spring batch 아키텍쳐(구성)
•Application : 개발자가 spring batch 프레임워크를 사용해 코딩한 커스텀 코드 부분
7. Spring batch 를 사용하기 위한 준비
- Spring-batch-core가 Batch-infrastructure 의 dependency를 가지고 있으므로 Spring-batch-core만 설정해주면 된다.(필수)
- Spring batch test를 위해 추가
8. 일반적인 배치 어플리케이션에 대한 가이드 라인
9. Spring Batch 3.0 에서 추가된 기능
- JSR-352를 지원해서 표준배치스펙과 완벽하게 호환된다.
<?xml version="1.0" encoding="UTF-8"?>
<job id="myJob3" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="step1" >
<batchlet ref="testBatchlet" />
</step>
</job> -
Spring Batch Integration은 원래 Spring Batch Admin의 하위모듈이었는데 승격되어 spring batch 3.0부터 포함되었다.
-
Spring 4, Java8 지원 (최소 Java 6 이상에서 동작)
-
JobScope 지원 (기존에는 StepScope만 지원되었다.)
-
SQLite 지원
10. Step Scope
위의 코드는 컴파일시에 resource 값이 정해진다.
런타임시에 입력 받은 값을 resourc로 사용하고 싶다면? Late binding 이 필요하고 이를 가능하도록 스프링 배치에서는 step scope와 job scope를 제공해준다.
- Step scope : step scope로 설정된 빈은, step 실행이 시작 될때 생성된다
-
scope="step"은 스프링의 디폴트 설정이 아니기 때문에 반드시 명시적으로 설정해야한다.
11. Job Scope
12. 배치 아키텍쳐의 단순화된 버젼
Spring batch도 이 배치 아키텍쳐를 기준으로 개발되었으며, 다이어그램에 나오는 배치 도메인 언어에 대한 개념 확실히 잡자.
13. Job 관련 배치 도메인
Job | 배치 프로세스를 캡슐화한 엔티티로, 1개 이상의 Step을 담고 있는 컨테이너로 볼 수 있다. |
JobInstance | Job 실행의 논리적인 개념을 의미한다. 매일 00시에 실행되는 EndOfDay Job을 보면, 2007/05/05의 실행과 2007/05/06의 실행은 각각 분리되어 추적 되어야 한다. 이를 가능하게 하는 논리적인 개념이 바로 JobInstance 이다. (JobInsatnce = Job + JobParameters) |
JobParameters | batch job을 시작시킬 때 사용한 파라미터의 집합으로, 그 쓰임새는 아래와 같다. 1.JobInstance를 식별하기 위해 사용
2.Job 실행 동안 참조할 데이터로 사용
|
JobExecution | Job을 실행하는 한번의 시도를 의미한다. 실행은 성공 또는 실패로 끝날 수 있지만, 성공적으로 완료되지 않으면, 해당 JobInstance는 완료되지 않은 것으로 보고 재실행 시킬 수 있다. 재실행 시에는, JobInstnace는 생성되지 않고 기존의 것이 이용되지만 JobExecution 은 새로운 실행이므로 새로 생성된다. 또한 Job 실행 상태 및 지속되어야 할 속성들을 가지고 있으며 JobRepository를 통해 이 정보들이 db에 저장된다. |
JobExecution 객체가 가지고 있는 속성들
status | 실행 상태를 나타내는 BatchStatus 객체이다. COMPLETED, STARTING, STARTED, STOPPING, STOPPED, FAILED, ABANDONED, UNKNOWN |
startTime | Job 실행이 시작될 때의 시스템 시간(java.util.Date) |
endTime | 성공/실패여부를 떠나 Job 실행이 끝났을 때의 시스템 시간(java.util.Date) |
exitStaus | 실행결과를 의미하는 ExitStatus 객체로, job 실행을 호출한 caller에게 리턴 할 exit code를 가지고 있어 가장 중요한 속성이다. (이 return된 값으로 caller는 재처리와 같은 다른 기능을 처리할 수도 있다.) |
createTime | JobExecution이 생성 되었을 때의 시스템 타임(java.util.Date) Job은 아직 시작되지 않았을 것이므로 startTime값은 없지만 항상 createTime은 존재한다. job 레벨의 executionContext 에서 이 값이 필요하므로 항상 생성된다. |
lastUpdated | JobExecution객체가 존재했던 마지막 시스템 타임(java.util.Date) |
executionContext | 실행 중 보관되어질 필요가 있는 사용자 data 를 담고 있는 보관소이다. |
failureExceptions | Job 실행 동안 발생한 exception 목록이다. |
이 속성들은 job 실행의 존재와 상태를 결정하는데 사용되므로 아주 중요하다.
14. Step 관련 배치 도메인
Step | 독립적, 순차적인 batch job의 단계를 캡슐화한 domain 객체, 실제 batch processing을 정의하고 컨트롤하기 위해 필요한 모든 정보를 담고 있다. 즉 step안에 실제 배치 업무가 담긴다. |
StepExecution | step을 실행하는 한번의 시도를 의미하며, step이 시작될 때 마다 매번 생성된다. Job에 여러 개의 step이 정의되어 있는 경우, 어떤 step이 실패하면 그 다음에 실행될 step도 시작되지 않는다. |
StepExecution객체가 가진 속성들
status | 실행 상태를 나타내는 BatchStatus 객체 |
startTime | 실행 시작 시간(java.util.Date 형식) |
endTime | 실행이 성공했든 실패했든 실행이 끝난 시간(java.util.Date 형식) |
exitStatus | 실행 결과를 나타내는 ExitStatus 객체 caller에게 반환할 exit code를 가지고 있기 때문에 가장 중요하다. |
executionContext | 실행 동안 보존될 필요가 있는 사용자 data를 담고 있는 객체 |
readCount | 성공적으로 읽혀진 item 개수 |
writeCount | 성공적으로 쓰여진 item 개수 |
commitCount | 실행하는 동안 커밋 된 transaction의 수 |
rollbackCount | 실행하는 동안 롤백된 transaction의 수 |
readSkipCount | read 실패시 skip 갯수 |
processSkipCount | process 실패시 skip 갯수 |
filterCount | ItemProcessor에 의해 filter된 item 의 개수 |
writeSkipCount | write 실패시 skip 갯수 |
15. ExecutionContext
(database를 사용해서 메타정보를 저장하는 경우라면)
앞의 EndOfDay job 예제에서 DB안으로 파일을 써넣는 작업을 하는 loadData라는 step이 있다고 가정해보라.
첫 번째 실패 이후 meta-data table은 아래와 같다.
다음날 job이 restart 된다고 가정해보자.
step이 restart 될 때, 지난 실행의 ExecutionContext의 값이 database로 부터 조회되어 재구성되어진다.
ItemReader가 open될 때 ItemReader는 executionContext 안에 어떤 값이 저장되어 있는지 확인 할 수 있고
거기서 부터 스스로를 초기화 할 수있다.
위의 코드가 실행된 후에는 현재 라인은 40322 번째가 될 것이다.
즉, executionContext에 사용자 Data를 넣어둠으로써 이전 Job 실행에서 그만둔 자리에서부터 다시 시작 할 수 있게 코딩 할 수 있다.
(개발자가 어떻게 코딩 하느냐에 따라 restart 시에 어떻게 실행될지 결정된다. 다만, 프레임워크는 좀 거들 뿐…)
16. JobRepository
17. JobLauncher
주어진 JobParameters 를 가지고 Job을 시작 시키기 위한 인터페이스다.
위 JobLauncher 의 코드를 보면, JobRepository로 부터 유효한 JobExecution을 획득될 것이 기대된다.
즉, JobExecution을 생성했다는 것은 Job을 실행 시킨 것을 의미한다.
18. ItemReader
*chunk : 하나의 트랜잭션안에서 처리되는 item 덩어리
20. ItemProcessor
Chunk-Oriented Processing 에서 ItemReader, ItemWriter는 필수이지만 ItemProcessor는 옵션이다
21. 배치 어플리케이션의 전체 구성(Batch 아키텍쳐 Big Picture)
Batch 아키텍처는 크게 Batch Application의 기동 및 운영관리를 위한 Client, 실제 Batch Job의 수행을 위한 Batch Application Framework, 데이터 및 타 시스템과 연계를 위한 Data/Integration 영역으로 구성되며, 서로간의 연관 관계는 다음과 같이 정의됨
22. Job실행 하기 전 batch meta table 생성하기
(Database 로 배치 실행 이력을 관리하고자 할 경우에만)
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="org/springframework/batch/core/schema-drop-mysql.sql" />
<jdbc:script location="org/springframework/batch/core/schema-mysql.sql" />
</jdbc:initialize-database>
23. Job 설정하기 – 1) xml namespace 방식(기본 설정)
24. Job 설정하기 – 1) xml namespace 방식(주요 옵션 설정)
Job 실행 동안 Job 라이프사이클 이벤트 발생시점에 사용자가 정의한 코드가 실행 될 수 있도록 이벤트 리스너를 추가할 수 있다.
SimpleJob는 적절한 시간에 JobListener를 호출한다.
JobListener로는 JobExecutionListener가 유일하다.
Job 런타임 실행시, 입력된 Job 파라미터의 유효성을 체크 하는 validator를 설정할 수 있다.
DefaultJobParameterValidator는 단순히 필수파라미터를 체크하는 JobParameterValidator 의 단순한 구현체이다.
복잡한 유효성 체크가 필요하면, JobParametersValidator 인터페이스를 직접 구현하라.
25. Job 설정하기 – 2) 자바설정(Spring Batch 2.2.0 부터 Spring 3 부터 지원하는 Java config가 지원된다. )
bean | Bean name |
JobRepository | jobRepository |
JobLauncher | jobLauncher |
JobRegistry | jobRegistry |
PlatformTransactionManager | transactionManager |
JobBuilderFactory | jobBuilders |
stepBuilderFactory | stepBuilders |
나. BatchConfigurer 인터페이스를 구현하는 방법
@EnableBatchProcessing에서 제공하는 기본 빈 사용하지 않고 직접 설정하고자 할때, BatchConfigurer 인터페이스를 구현한다.
26. JobRepository 설정하기 – 1)
Namespace로 설정하거나 JobRepositoryFactoryBean을 통해 설정할 경우, 자동으로 JobRepository 에 대한 트랜잭션 어드바이스가 설정된다.
그렇지 않은 경우, AOP를 사용해서 트랜잭션 어드바이스 설정을 직접 해주는 것이 필수이다. (아마 직접할 일은 없을 것 같다.)
(batch namespace를 사용해서 설정하면 아래와 같은 내용을 포함하고 있다고 생각하면 된다.)
27. JobRepository 설정하기 – 2)
28. JobLauncher 설정하기
29. Job 실행하기
command line에서 Job을 시작시킨다면 새로운 JVM이 각각의 Job을 위해 인스턴스화 될 것이므로 모든 Job은 그 자신을 위한 JobLauncher를 가질 것이다.
웹 컨테이너 내에서 실행되는 경우에는 대개 비동기 방식으로 설정되어진 한 개의 JobLauncher 만 가질 것이다.
1) Command Line에서 Job 실행하기
Job을 시작시키는 스크립트는 JVM을 시작시켜야 하기 때문에 실행을 위한 엔트리 포인트로써 main 메소드를 가진 한개의 class가 필요하다. 스프링 배치는 단지 이 목적만을 위해 CommandLineJobRunner를 제공한다.
1번째 인자(JobPath) : job설정파일의 위치로, 이 xml 설정파일에는 job을 실행시키는데 필요한 모든것이 포함되어 있어야 한다.
2번째 인자(jobName) : 실행할 Job 이름
이 두 인자 뒤에 전달되는 나머지 모든 인자들은 JobParameters 로 간주되고 인자의 형식은 name=value 형식이어야 한다.
- job 프로세스가 스케줄러(호출자)에게 전달하는 실행결과를 나타내는 숫자값 (가장 간단한 경우, 0은 성공 1은 실패이다. )
- JobExecution의 ExitStatus 는 프레임워크 또는 개발자에 의해 설정되는 exit code 속성을 가지고 있다.
- JobLauncher의 반환값인 JobExecution을 받은 CommandLineJobRuuner는 이 속성값(문자)을 ExitCodeMapper 인터페이스를 사용하여 숫자값으로 변환한다.
2) 웹 컨테이너 내에서 Job 실행하기
30. 메타 데이타 이용 -
1) JobExplorer
JobExplorer는 JobRepository와 같은 테이블을 사용하기 때문에 JobRepository 의 table prefix 설정을 변경한 경우 JobExplorer 설정도 동일하게 변경해야한다
2) JobRegistry
이것은 Child Context를 생성하고 그 Child Context에 선언된 job을 등록하는 라이프사이클 컴포넌트이다.
이걸 사용하면 Job Registry에 유니크한 job 이름을 전역적으로 사용할 수 있다.
만약 xml에 선언된 ItemReader의 이름을 reader로 하는 경우, 해당 xml 파일이 다른 많은 xml 설정 파일에 import된다면
reader는 충돌 되거나 다른 것으로 오버라이드 될거라고 예상하지만, AutomaticJobRegistrar 를 사용하면 이를 방지해준다.
3) JobOperator
4) JobParametersIncrementer
ㄱ. 매번 Job을 실행할 때마다 겹치지 않는 JobParameters를 자동으로 만들기 위해 사용하는 것이 JobParametersIncrementer 이다
1. Step 이란?
2. Chunk-Oriented Processing
parent | 부모 step을 지정한다. |
abstract | step 상속을 위해 필수 요소인 reader, writer 가 없는 Abstract Step을 정의 할 수 있다. |
merge | step 내에 있는 <listeners/>같은 list요소는 상속시, child step의 list요소에 의해 기본적으로 오버라이드 된다. 만약 오버라이드가 아닌 병합을 하고 싶은 경우에는 , merge=true를 설정해야한다. |
3. Chunk-Oriented Processing – Restart를 위한 step 설정
(예를 들면, 오직한번 실행되어야 하는 step과 무한히 실행해도 되는 step등등)
4. Chunk-Oriented Processing – Skip logic 설정하기
항목 | 설명 | |
skip-limit | Skip 할 수 있는 최대 횟수를 지정 default=0 이므로 꼭 지정해줘야 Skip기능 이용 할 수 있음 |
|
<skippable-exception-classes> | <include> | skip 해야하는 Exception 범위를 지정 |
<skippable-exception-classes> | <exclude> | include로 지정한 exception의 하위 exception 중, Skip하지 않을 Exception 지정 |
5. Chunk-Oriented Processing – retry logic 설정하기
반면에, Process 과정과 Write과정에서 발생하는 데이터 선점에 대한 DeadlockLoserDataAccessException 등은 Retry를 통해 해결할 수 있다. 즉, 다른 프로세스에서 처리중인 데이터에 새로운 프로세스가 접근하는 경우 Lock이 걸려 있어 에러가 발생하는데 잠시 후 재시도 하면 성공할 가능성이 있는 것이다.
6. Chunk-Oriented Processing – Rollback 설정
나.Tansactional Readers
디폴트는 false 이므로, process나 write에서 처리 하다 retry 되는 경우, 다시 시도 할때 reader를 통해 조회하지 않고 버퍼에 있는 item을 이용 한다
7. Chunk-Oriented Processing – Transaction설정
transaction-attributes는 step에 대해 isolation, propagation, timeout 설정을 하기 위해 사용된다
8. TaskletStep
9. StepListener
10. StepListener - 1. StepExecutionListener
11. StepListener - 2. ChunkListener
12. StepListener - 3. ItemReaderListener
beforeRead | ItemReader의 read 메소드가 호출되기 전에 호출된다. |
afterRead | ItemReader의 read 메소드 실행이 성공적으로 완료된 후에 호출된다.(즉, item을 성공적으로 읽은 후에 호출) |
onReadError | ItemReader의 read 메소드내에서 읽기 중에 에러가 발생한 경우 호출된다. 발생한 exception을 통해 로깅작업이 가능하다. |
상응하는 어노테이션
@BeforeRead
@AfterRead
@OnReadError
13. StepListener - 4. ItemProcessListener
14. StepListener - 6. SkipListener
onSkipInRead | read 중에 아이템이 스킵될 때마다 호출된다. 같은 아이템이 계속 스킵될 때마다 등록될 수 있기 위해 롤백이 발생할 수 있다. |
onSkipInProcess | process 중에 item이 스킵될 때 호출된다. 이때 아이템은 성공적으로 조회되었으므로 스킵된 아이템이 전달된다. |
onSkipInWrite | write 중에 item이 스킵될 때 호출된다. 이때 아이템은 성공적으로 조회되었으므로 스킵된 아이템이 전달된다. |
상응하는 어노테이션
@OnSkipInRead
@OnSkipInProcess
@OnSkipInWrite
SkipListener와 transaction
SkipListener의 가장 일반적인 이용은 스킵된 아이템에 대한 로깅이다. 이렇게 기록된 로그를 이용해 다른 프로세스나 사람이 직접 스킵을 만들어낸 이슈에 대해 수정하거나 계산하는데 이용될 수 있다. 트랜잭션이 롤백 될수 있는 많은 경우가 있기 때문에, 스프링 배치는 2가지를 보장한다.
1. 에러 발생시 적합한 스킵 메소드는 아이템 마다 오직 한번만 호출된다.
2. SkipListener는 트랜잭션이 커밋되기 직전에 호출된다. 그러므로 ItemWrite 내부 실패에 의해 호출된 리스너내의 어떤 트랜잭셔널한 리소스가 롤백되지 않도록 보장한다.
15. Step 흐름 제어하기 - 순차적 흐름
16. Step 흐름 제어하기 - 조건적인 흐름
17. transition element - next
on 속성에는 Step 실행 결과인 ExitStatus의 exitCode에 대한 매칭 패턴을 사용할 수 있다.
사용 가능한 2가지 패턴은 *, ? 이다.
on 속성이 참조하는 ExitStatus의 exitCode는 StepExecutionListener의 afterStep으로 변경할 수 있다. 이 메소드가 null이 아닌 ExitStatus를 리턴하면 해당 Step의 ExitStatus는 이 값으로 변경된다. (자세한 내용은 뒤에)
Batch Status Vs. Exit Status
18. transition element – stop transition element
이들 stop transition elemen는 Job내의 Step에 대한 BatchStatus와 ExitStatus에는 전혀 영향을 주지 않는다. 오직 Job의 최종 status에만 영향을 준다.
19. transition element – stop transition element (end)
20. transition element – stop transition element (fail)
21. transition element – stop transition element (stop)
Job 하위 element로 step 실행 흐름 제어와 관련된 태그.
'spring' 카테고리의 다른 글
2. Spring Batch 가이드 - Batch Job 실행해보기 (0) | 2023.02.09 |
---|---|
1. Spring Batch 가이드 - 배치 어플리케이션이란? (0) | 2023.02.09 |
Spring Boot, 프로젝트 생성하기 (0) | 2021.12.02 |
전자정부프레임워크 버전별 구성 및 서블릿 컨테이너 버전 지원 (0) | 2021.05.14 |
전자정부 표준프레임워크 2016 우수사례 (0) | 2021.04.20 |