Spring

[Spring Batch] 스프링 배치 도메인 정리

꾸준함. 2023. 7. 6. 11:04

Job

  • 배치 계층 구조에 최상위 개념으로 하나의 배치 작업 자체를 의미
    • ex) "elasticsearch에 저장된 로그를 RDB로 옮기는 배치" -> Job
  • 배치 작업을 어떻게 구성하고 실행할 것인지 전체적으로 설정하고 명세해 놓은 객체
  • 반드시 한 개 이상의 Step을 구성
  • Spring Batch가 기본 구현체 제공
    • SimpleJob
    • FlowJob

 

JobInstance

  • Job이 실행될 때 생성되는 Job의 논리적 실행 단위 (실행되는 시점)
    • 하루에 한 번씩 배치 Job이 실행될 경우 매일 실행되는 각각의 Job을 JobInstance로 표현
    • 따라서, Job과 JobInstance는 1:N 관계
  • JobInstance 생성 및 실행 기준
    • Job과 JobParameter 조합이 신규일 경우 새로운 JobInstance 생성
    • 이전과 동일한 Job과 JobParameter 조합일 경우 기존에 생성된 JobInstance 반환
    • 이때 JobParameter는 해싱을 통해 JobKey로 변환되어 spring-batch-core 라이브러리에서 생성해 주는 BATCH_JOB_INSTANCE 테이블에 저장됨
    • 따라서, JOB_NAME과 JOB_KEY 칼럼의 조합을 기준으로 JobInstance 생성할지 판단

 

 

JobParameters

  • Job을 실행할 때 함께 포함되어 사용되는 파라미터를 가진 도메인 객체이며 JobInstance와 1:1 관계
    • 하나의 Job에 존재할 수 있는 다수의 JobInstance를 구분하기 위한 파라미터
  • 코드 단에서는 JobParameterBuilder를 통해 생성 가능
  • 어플리케이션 실행 시 주입하여 SpEL 문법을 이용할 수 있음
  • spring-batch-core 라이브러리에서 생성해 주는 BATCH_JOB_EXECUTION_PARAMS 테이블에 저장

 

 

 

 

JobExecution

  • JobInstance에 대한 한번의 시도를 의미하는 객체로서 Job 실행 중에 발생한 정보들을 저장하고 있는 객체
    • ex) 배치 시작 시간, 종료 시간, 종료 상태 등등
  • JobExecution은 "COMPLETED", "FAILED"와 같은 Job의 실행 결과 상태를 가지고 있음
  • JobExecution의 실행 상태 결과가 COMPLETED일 경우 JobInstance 실행이 완료된 것으로 간주하여 재 실행 불가
    • JobInstanceAlreadyCompleteException 예외 발생
  • JobExecution의 실행 상태 결과가 FAILED일 경우 JobInstance 실행이 완료되지 않다고 판단하여 재 실행 가능
    • JobParameter가 동일한 Job 즉, 같은 JobInstance여도 재 실행 가능
    • 따라서, COMPLETED가 될 때까지 하나의 JobInstance 내 여러 JobExecution이 생성 가능 (1:N 관계)
  • spring-batch-core 라이브러리에서 생성해 주는 BATCH_JOB_EXECUTIO 테이블에 저장

 

Step

  • Job을 구성하는 독립적인 하나의 단계
  • 배치 작업을 어떻게 구성하고 실행할 것인지에 관한 Job의 세부 작업을 Task 기반으로 설정하고 명세한 객체
  • 앞서 언급했듯이 모든 Job은 최소 하나 이상의 step으로 구성
  • Spring Batch가 기본 구현체 제공
    • TaskletStep
    • PartitionStep
    • JobStep
    • FlowStep

 

StepExecution

  • JobExecution과 유사한 객체로 Step 실행 중에 발생한 정보들을 저장하고 있는 객체
    • 시작 시간, 종료 시간, 상태, commit count, rollback count 등의 속성을 지님
    • Step이 시도될 때마다 생성되므로 Step과 StepExecution은 1:N 관계
    • 각 StepExecution은 하나의 JobExecution을 부모로 가짐
    • 정리하자면 Job : JobExecution = 1 : N, JobExecution : StepExecution = 1 : N
  • Job이 FAILED 처리됨에 따라 재시작되더라도 이미 성공한 Step은 skip이 되고 실패한 Step만 재 실행
    • 이전 단계 Step이 실패함에 따라 현재 Step이 실행되지 않았다면 현재 step에 대한 StepExecution은 생성 X
    • Job 내 Step들의 StepExecution이 하나라도 실패할 경우 JobExecution은 실패 처리
  • spring-batch-core 라이브러리에서 생성해주는 BATCH_STEP_EXECUTION 테이블에 저장

 

StepContribution

  • Chunk 프로세스의 변경 사항을 버퍼링 후 StepExecution 상태를 업데이트하는 도메인 객체
  • ExitStatus의 기본 종료코드 외 사용자 정의 종료코드를 생성해서 저장 가능

 

 

ExecutionContext

  • Map 객체와 같은 key-value 컬렉션으로 JobExecution 혹은 StepExecution 객체의 상태를 저장하는 공유 객체
    • ConcurrentHashMap 
    • spring-batch-core 라이브러리에서 생성해주는 BATCH_JOB_EXECUTION_CONTEXT, BATCH_STEP_EXECUTION_CONTEXT 테이블에 저장
  • 공유 범위
    • Job 범위 - 각 Job의 JobExecution에 저장되며 Job 간에는 공유가 안되지만 해당 Job의 Step 간에는 서로 공유 됨
      • Process 내 Thread끼리 힙 메모리 공유하는 것과 비슷한 개념?
    • Step 범위 - 각 Step의 StepExecution에 저장되며 Step마다 독립적, Step 간 공유 안됨
  • 실패한 Job에 대해 재 실행 시 이미 처리한 Row 데이터는 건너뛰고 처리하지 않은 Row를 수행할 때 상태 정보를 활용

 

JobRepository

  • 배치 작업 중의 정보를 저장하는 저장소
  • 배치 작업의 수행과 관련된 모든 메타데이터를 저장
    • JobLauncher, Job, Step 구현체 내부에서 CRUD 기능을 처리

 

https://docs.spring.io/spring-batch/docs/current/reference/html/job.html

 

JobRepository 설정

 

  • @SpringBootApplication 어노테이션이 선언된 클래스에 @EnableBatchProcessing 어노테이션만 선언하면 JobRepository가 자동으로 Bean으로 생성됨
  • BatchConfigurer 인터페이스를 직접 구현 혹은 BasicBatchConfigurer를 상속해서 JobRepository 설정 커스터마이징 가능
    • JDBC 방식으로 설정 - JobRepositoryFactoryBean
    • In Memory 방식으로 설정 - MapJobRepositoryFactoryBean
  • JobRepositoryFactoryBean
    • 내부적으로 AOP 기술을 통해 트랜잭션 처리
    • 트랜잭션 isolation의 default 값은 SERIALIZABLE로 최고 수준
      • 일반적인 서비스에서는 성능 저하 요인이나 배치의 경우 동시 접근이 이루어지는 케이스가 적기 때문에 괜찮음
      • READ_COMMITED, REPEATABLE_READ로 변경 가능
    • 메타 테이블의 Table Prefix를 BATCH_에서 다른 값으로 변경 가능
  • MapJobRepositoryFactoryBean
    • PoC 개발과 같이 빠른 개발이 필요할 때 사용
    • 굳이 DB에 저장하고 싶지 않을 경우에 사용

 

예시 코드


 

 

* factory.getObject를 반환하면 Proxy 객체가 생성되며 이를 통해 AOP 기술 적용 가능



JobRepository 설정을 위와 같이 변경 후 JobRepositoryListener를 생성한 뒤 JobBuilderFactory에 listener를 지정하면 변경된 설정이 적용됩니다.



 

JobLauncher

  • 배치 작업을 실행시키는 역할
  • Job과 JobParameters를 매개변수로 받으며 요청된 배치 작업을 수행한 후 최종 client에게 JobExecution 반환
  • SpringBoot Batch에서는 JobLauncherApplicationRunner가 자동적으로 JobLauncher를 실행
  • 동기적 실행 (sync)
    • taskExecutor를 default 값인 SyncTaskExecutor로 설정할 경우 
    • JobExecution을 획득하고 배치 처리를 최종 완료한 이후 Client에게 JobExecution을 반환
    • 배치 처리 시간이 길어도 상관없는 Scheduler에 의한 배치 처리에 적합
  • 비동기적 실행 (async)
    • taskExecutor를 SimpleAsyncTaskExecutor로 설정할 경우
    • JobExecution을 획득한 후 Client에게 바로 JobExecution을 반환하고 배치처리 완료 (JobExecution EXIT_CODE 칼럼이 처리 중에는 UNKNOWN)
    • 배치 처리 시간이 길 경우 response가 늦어지지 않아야 하는 HTTP 요청에 의한 배치 처리에 적합

 

예시 코드

 

 

 

실행한 job 내 step에서 5초 정도 걸리는 로직이 수행된다고 가정하고 Thread.sleep(5000); 추가한 뒤 동기 api와 비동기 api를 호출하면 확연한 차이를 보입니다.

동기 api의 경우 5초 뒤에 응답이 오고 비동기 api의 경우 응답은 바로 오지만 JobExecution 테이블 내 EXIT_CODE가 UNKNOWN이였다가 5초 뒤 COMPLETED로 바뀌는 것을 확인할 수 있습니다.

 

 

비고

spring-batch-core에서 생성해주는 테이블 DDL은 아래 경로에서 확인 가능합니다.

spring-batch-core jar 파일 > org.springframework.batch.core > *.sql

저는 MySQL을 사용하고 있으므로 schema-mysql.sql을 사용하였고 DDL은 아래와 같습니다.


 

보다 자세한 내용은 아래 블로그를 참고하시는 것을 추천드립니다!

https://khj93.tistory.com/entry/Spring-Batch%EB%9E%80-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

Spring Batch란? 이해하고 사용하기(예제소스 포함)

들어가기 앞서.. Spring Batch에는 굉장히 많은 설정과 기능들이 존재합니다. 해당 포스팅에서는 기초적인 Spring Batch에 대해서 설명하고 사용하는 예제에 대해서 설명을 하려고 합니다. Spring Batch를

khj93.tistory.com

 

참고

스프링 배치 - Spring Boot 기반으로 개발하는 Spring Batch (정수원 강사님)

반응형