개발공부/SPRING

[Spring Batch] Spring Batch 개념

키크니개발자 2023. 6. 4. 16:53

왜 스프링 배치를 사용하는가? 

  • 배치 처리는 컴퓨터에서 사람과 상호 작용 없이 이어지는 프로그램의 실행 → 한번 요청으로 그 시스템 내에서 종료가 됨
  • 사용자와의 상호 작용이 주력인 웹 애플리케이션과는 지향점이 다름
  • web : 실시간 처리 / QA 용이성
  • batch : 후속 처리 / QA 복잡성

 

언제 사용하는가?

  • 일정 주기로 실행되어야 할 때
  • 웹어플리케이션으로 실시간 처리가 어려운 대량의 데이터를 처리할 때
  • 배치는 대량의 데이터를 처리하기 위해서 여러 가지 기능을 제공 → 개발자는 업무 로직의 구현에만 집중하고 공통적인 기반 기술은 프레임워크가 담당
    • pageSize, chunkSize 등이 프레임워크 단위에서 지원이 됨
    • 하지만 Quartz는 지원해주지 않음 -> Spring Batch와 Quartz를 함께 사용하려면 Quartz 스케줄러를 스프링 빈으로 등록하고, Spring Batch Job을 Quartz Job으로 래핑하여 Quartz 스케줄러에서 실행하도록 설정해야 합니다.

스프링 배치 아키텍처

  • 실제 비지니스 로직이 들어감 → 개발자는 업무 로직의 구현에만 집중하고 공통적인 기반기술은 프레임워크가 담당
  • 배치 meta 테이블 정보, Job을 실행, 모니터링, 관리하는 API로 구성
  • JobLauncher, Job, Step, Flow 등이 속함
  • Application, Core 모두 공통 Infrastructure 위에서 빌드
  • Job 실행의 흐름과 처리를 위한 틀을 제공 - Reader, Processor, Writer, Skip, Retry 등

 

스프링 배치 메타 테이블

  • 스프링 배치의 실행 및 관리를 위한 목적으로 여러 도메인들 - Job, Step, JobParameter 의 정보들을 저장, 업데이트, 조회할 수 있는 스키마
  • 과거, 현재의 실행에 대한 성공과 실패 여부 등을 관리 → 배치 운용에 있어 리스크 발생 시 빠른 대처 가능
  • Job 관련 테이블
    • batch_job_instance
      • job이 실행될 때 jobInstance 정보가 저장 → job_name / job_key를 키로 하여 하나의 데이터가 저장 → 그래서 동일한 job_name과 job_key로 중복 저장될 수 없음
      • job_name: job을 구성할 때 부여하는 이름
      • job_key: job_name과 jobParameter를 합쳐 해싱한 값
    • batch_job_execution
      • job의 실행정보가 저장 → job 생성 시간, 시작 시간, 종료 시간, 실행 상태(성공했는지.. 실패했는지..), 종료 메시지 등을 관리
    • batch_job_execution_param
      • job과 함께 실행되는 jobParamter 정보를 저장
    • batch_job_execution_context
      • job의 실행동안 상태정보, 공유 데이터를 직렬화(json)해서 저장
      • step간 공유 가능
  • Step 관련 테이블
    • batch_step_execution
      • step의 실행정보가 저장 → step 생성 시간, 시작 시간, 종료 시간, 실행상태, 종료 메시지 등을 관리
    • batch_step_execution_context
      • step의 실행동안 상태정보를 직렬화(json)해서 저장
      • step 별로 저장되며 step간 공유 불가능

 

Job / Step / Tasklet

  • Job 
    • 배치 계층에서 가장 상위에 있는 개념 → 하나의 배치 작업 자체를 의미
    • @JobConfiguraion을 통해 생성되는 객체 단위 → 배치작업을 어떻게 구성하고 실행할 것인지 전체적으로 설정하고 명세해 놓은 객체
    • 여러 step을 포함하고 있는 container 역할 → 반드시 하나의 step이 있어야함
    • 기본 구현체
      • SimpleJob : 순차적으로 Step을 실행시키는 Job
      • FlowJob : 특정한 조건과 흐름에 따라서 Step을 구성하고 실행시키는 Job
    • jobInstance
      • job의 설정과 구성은 동일하지만 job이 실행되는 시점에 처리하는 내용은 다름 → 예를 들어서 5분마다 실행되는 job은 서로 다른 jobInstance를 가져야 함
      • 처음 시작하는 job Name + jobParameter의 경우 새로운 jobInstance 리턴, 이전과 동일한 job Name + jobParameter의 경우 이미 존재하는 jobInstance 리턴
      • 내부적으로 jobName + jobKey를 통해서 jobInstance를 얻음
      • batch_ job_instance 테이블과 매핑
    • jobParamter
      • job을 실행할 때 함께 포함되어 사용되는 파라미터를 가진 도메인 객체
      • jobParamter와 jobInstance는 1:1관계
      • jobParameter를 사용하기 위해서 @JobScope, @StepScope 선언 필수
      • batch_job_execution_param 테이블과 매핑
    • jobExecution
      • jobInstance 실행 중 발생한 정보들을 저장하고 있는 객체
      • jobParamter 정보, executionContext 정보, 시작 시간, 종료 시간, 상태(시작됨, 완료, 실패)의 속성
      • jobExecution의 실행 상태 결과에 따라서
        • COMPLETED’면 jobInstance 실행이 완료된 것으로 간주해서 재실행 불가
        • FAILED’면 jobInstance 실행이 완료되지 않은 것으로 간주해서 재실행 가능 → jobParamter가 동일한 값일 지라도 jobInstance 계속 실행 가능
      • batch_job_execution 테이블과 매핑

 

  • Step
    • job을 구성하는 독립적인 하나의 단계로 실제 배치 처리를 정의하고 컨트롤하는데 필요한 정보를 가지고 있는 객체
    • 단순한 단일 태스크 뿐 아니라 입력, 처리, 출력 관련된 복잡한 비지니스 로직을 포함하는 모든 설정들을 담고 있음
    • 기본 구현체
      • TaskletStep
        • 가장 기본이 되는 클래스로서 Tasklet 타입 구현체들을 제어
        • return this.stepBuilderFactory.get("step").tasklet(myTasklet()).build() → 직접 생성한 tasklet 실행
        • return this.stepBuilderFactory.get("step").<>chunk(100).reader(reader()).writer(wrtier()).build() → ChunkOrientedTasklet 실행
      • PartitionStep : 멀티 스레드 방식으로 Step을 여러 개로 분리해서 실행
      • JobStep : step 내에서 job을 실행
      • FlowStep : step 내에서 flow를 실행
    • StepExecution
      • step에 대한 한번의 시도를 의미하는 객체로 step 실행 중에 발생한 정보들을 저장하고 있는 객체
      • jobExecution 정보, executionContext 정보, 시작 시간, 종료 시간, 상태, commit count, rollback count 등의 속성
      • step이 시도될 때마다 stepExecution 객체가 생성 → 이전 단계 step이 실패했다 stepExecution을 생성하지 않고 재활용
      • job이 재시작하더라도 이미 성공적으로 완료된 step은 재실행되지 않고 실패한 step만 실행
      • jobExecution과의 관계
        • step의 stepExecution이 모두 정상적으로 완료 되어야 JobExecution이 정상적으로 완료 → 하나라도 실패하면 jobExcecution은 실패
      • batch_step_execution 테이블과 매핑

 

  • ItemStream
    • open, update, close 메소드가 있는데 ItemReader와 ItemWriter 처리 과정 중 상태를 저장하다가 오류가 발생하면 상태를 참조해서 실패한 곳에서 재시작하도록 지원
    • ExecutionContext를 매개변수로 받아서 상태 정보를 업데이트
    • ItemReader와 ItemWriter 는 ItemStream을 구현
  • executionContext (jobExecution, stepExecution 클래스에 속해있음)
    • 프레임워크에서 유지 및 관리하는 키/값으로 된 컬렉션으로 StepExecution, JobExecution 객체의 상태를 저장하는 공유 객체
      • Map<String, Object> map = new ConcurrentHashMap<>();
    • db에 직렬화 한 값으로 저장 → {"key":"value"} - batch_job_execution_context, batch_step_execution_context
    • 공유 범위
      • step - 각 step의 stepExecution 클래스에 저장 → step간 공유할 수 없음
      • job - 각 job의 jobExecution에 저장 → job간 공유할 수 없음, step간 공유 가능
        • stepExecution의 경우 내부에 jobExecution 속성이 있어서 jobExecution에 정의된 executionContext 접근 가능 → 그래서 공유가 가능

반응형