BatchApplication

@EnableBatchProcessing

  • modular 옵션 활성화 시 ModularBatchConfiguration 동작
  • modular 옵션 비활성화 시 SimpleBatchConfiguration 동작
  • 초기화 관련 클래스
    • BatchAutoConfiguration
      • 스프링 배치가 초기화 될 때 자동으로 실행되는 설정 클래스
      • Job 을 수행하는 JobLauncherApplicationRunner 빈을 생성
    • SimpleBatchConfiguration
      • JobBuilderFactory 와 StepBuilderFactory 생성
      • 스프링 배치의 주요 구성 요소 생성 - 프록시 객체로 생성됨
    • BatchConfigurerConfiguration
      • BasicBatchConfigurer
        • SimpleBatchConfiguration 에서 생성한 프록시 객체의 실제 대상 객체를 생성하는 설정 클래스
        • 빈으로 의존성 주입 받아서 주요 객체들을 참조해서 사용할 수 있다.
      • JpaBatchConfigurer
        • JPA 관련 객체를 생성하는 설정 클래스
      • 사용자 정의 BatchConfigurer 인터페이스를 구현하여 사용할 수 있음

Job, Step, Tasklet

Job > Step > Tasklet 순서로 실행

  1. Configuration 설정: 하나의 배치 Job 을 정의하고 빈 설정
  2. JobBuilderFactory: Job 을 생성하는 빌더 팩토리
  3. StepBuilderFactory: Step 을 생성하는 빌더 팩토리
  4. Job: Job 생성
  5. Step: Step 생성
  6. Tasklet: Step 안에서 단일 태스크로 수행되는 로직 구현

Metadata Schema

  • DB 와 연동하기 위해서 꼭 생성되어야 하는 테이블
  • org.springframework.batch.core 에 schmea-*.sql 형태로 존재
  • 스키마 생성
    • 수동 생성: 쿼리 복사 후 직접 실행
    • 자동 생성: spring.batch.jdbc.initialize-schema 설정
      • ALWAYS: 스크림트 항상 실행, RDBMS 설정이 되어있을 경우 내장 DB 보다 우선으로 실행
      • EMBEDDED: 내장 DB 일때만 실행되며 스키마가 자동생성됨. 기본값
      • NEVER
        • 스크림트 항상 실행 안함
        • 내장 DB 일 경우 스크립트가 생성이 안되기 때문에 오류 발생
        • 운영에서 수동으로 스크립트 생성 후 NEVER 옵션으로 설정하는 것을 권장
    • MySQL 이나 PostgreSQL 을 사용하는 경우 별도의 Sequence Table을 생성해야 함

Job

  • 배치 계층 구조에서 가장 상위에 있는 개념
  • 하나의 배치 작업을 의미
  • 배치 Job 을 구성하기 위한 최상위 인터페이스
    • 기본 구현체는 스프링 배치가 제공
      • SimpleJob
        • 순차적으로 Step 을 실행시키는 Job
      • FlowJob
        • 특정한 조건과 흐름에 따라 Step 을 실행시키는 Job
        • Flow 객체를 실행시켜서 작업을 진행
    • 이 구현체를 Bean 으로 생성해서 실행시키는 구조
  • Job 은 한 개 이상의 Step 으로 구성

Test

JobExecutionAlreadyRunningException

CI/CD 설정을 통해 배치 애플리케이션에 대해 잦은 배포를 하게된다면 JobExecutionAlreadyRunningException 에러가 발생할 수 있다. 이때 아래 쿼리를 통해서 문제를 해결할 수 있다.

  • BatchStatus 와 ExitStatus 를 이용한 문제 해결 방법
UPDATE 
    batch_job_execution 
SET 
    end_time = current_timestamp, 
    status = 'FAILED', 
    exit_code = 'COMPLETED' 
WHERE 
   job_execution_id =
      (SELECT 
         MAX(job_execution_id) 
       FROM
         batch_job_execution 
       WHERE 
         job_instance_id = #{jobInstanceId}
      );

따라서, FAILED(BatchStatus) + COMPLETED(ExitStatus) 인 경우에는 Job 을 재시작 하지 않는다.