Controlling Step Flow


들어가며

이전에 우리는 Job이 n개의 Step으로 구성되어 있다는 것을 확인하였습니다.
Step은 일반적으로 순차적인 흐름으로 진행되지만, 조건에 따라 흐름을 제어할 수도 있습니다.
이번 포스팅에선 Step의 흐름 제어에 대해 알아보도록 하겠습니다.


Sequential Flow

일반적인 Step의 Flow입니다

@Bean
public Job job() {
    return this.jobBuilderFactory.get("job")
                .start(stepA())
                .next(stepB())
                .next(stepC())
                .build();
}
  • start() 메서드를 이용해 첫번째 Step을 호출합니다
  • next() 메서드를 이용해 다음 Step을 호출합니다
  • 우리는 Step이 A -> B -> C 순서로 진행되는 것을 쉽게 알 수 있습니다.

Conditional Flow

위 예제에서는 두가지 시나리오만 가능합니다

  1. Step이 성공하고 다음 Step이 실행됩니다
  2. Step이 실패하고, job이 실패됩니다

일반적으론 위의 flow로도 충분합니다.
하지만, Step이 실패할경우 job을 실패로 끝내기 보다
다른 Step을 호출한다면 어떻게 될까요???
아래의 Step flow를 확인 해보겠습니다

@Bean
public Job job() {
    return this.jobBuilderFactory.get("job")
                .start(stepA())
                    .on("*")
                    .to(stepB())
                .from(stepA())
                    .on("FAILED")
                    .to(stepC())
                .end()
                .build();
}
  • Step A가 성공할 경우 StepB가 실행됩니다.
  • Step A가 실패할 경우 StepC가 실행됩니다.

메서드가 직관적이기 때문에 무엇을 의미하는지 알 수 있습니다.
좀더 정확한 의미를 알기 위해 위의 코드를 잠시 살펴보겠습니다.

  • start()
    • Job의 Step 구성으로부터 시작할 Step을 정의
  • on()
    • ExitStatus를 Catch
    • '*'는 모든 ExitStatus를 정의
    • Status는 BatchStatus가 아닌 ExitStatus가 온다!!!
  • to()
    • 다음으로 이동할 Step을 정의
  • from()
    • Step의 상태값을 보고 일치할경우 캐치
  • end()
    • FlowBuilder를 종료
      이렇듯, 약간의 코드 추가로 Step의 실패가 Job의 실패로 유도되지 않도록 설계할 수 있습니다.

ExitStatus 설정!!!

Job Flow를 설정하면서 가장 많은 실수를 하는 부분이 이 부분이 아닐까 합니다!!

return stepBuilderFactory.get("stepA")
    .tasklet((contribution, chunkContext) -> {
        //////////////////////////////////////////////
        contribution.setExitStatus(ExitStatus.FAILED);
        //////////////////////////////////////////////
        return RepeatStatus.FINISHED;
    })

on() 메서드가 캐치하는 상태값은 Batch Status가 아닌 Exit Status입니다.
따라서 Step의 Flow를 컨트롤할 경우 setExitStatus() 메서드를 통해 상태값을 정의해야 합니다!!

public void setExitStatus(ExitStatus status) {
    this.exitStatus = status;
}

참조

jojoldu님 블로그 - 4. Spring Batch 가이드 - Spring Batch Job Flow
spring.batch.io - Configuring a Step

#Spring/Batch/Step-flow

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

Spring Batch chunk-oriented Step

들어가며

Step은 Job에서 독립적으로 실행되는 도메인 객체입니다. 하나의 Job에 N개의 Step이 올수 있습니다.
이전까진 Step의 tasklet을 이용해 간단한 예제를 살펴보았는데요, 이번 포스팅에선 chunk-oriented Step에 대해 알아보도록 하겠습니다.

 


Chunk-Oriented

Step은 tasklet/chunk 두가지 작업 방식을 지원합니다.
두 방식은 컨셉 차이가 있기 때문에 용도의 맞춰 프로그래밍을 하는게 좋습니다.
아래에서 tasklet, chunk 방식에 대해 간략히 알아보도록 하겠습니다.

  • tasklet
    • 단일 작업에 사용합니다
    • 일반적으로 Resource 삭제하거나 단순 쿼리를 질의하는 등 단일 작업을 수행합니다
  • chunk
    • 복잡한 작업세 사용합니다
    • Reader, Processor, Writer 3가지 단계로 구성됩니다
    • Reader, Writer는 필수이며 Processor는 선택적으로 사용됩니다
    • 즉, 데이터 읽기, 가공, 저장의 순으로 처리됩니다

간단히 두 방식의 차이점을 알아보았습니다.
tasklet은 복잡하지 않은 단일 작업에, chunk는 복잡하고 데이터를 읽어서 가공 처리해야 할 경우 사용하는 것이 적합합니다.
우리가 구현하고자 하는 대부분의 batch 작업은 복잡하고 거대하기 때문에 일반적으로 chunk-oriented 방식을 많이 사용합니다.


Chunk란?

Chunk란 데이터 작업의 묶음으로, Items를 묶어 처리되는 row수를 얘기합니다.
즉, Chunk 지향 프로세싱이란 한번에 하나씩 데이터를 읽어 Chunk 묶음을 만들고 Chunk 단위로 트랜젹선을 다루는 것을 말합니다.
Chunk 단위로 트랜잭션을 수행하기 때문에 실패할 경우엔 해당 Chunk만큼 롤백이 되고, 이전에 커밋된 트랜잭션 범위까지 반영이 된다는 것입니다.


Chunk-processing

그림으로, Chunk 지향 프로세싱의 처리를 알아보도록 하겠습니다.
Page Size 5000, Chunk Size 5000이라고 가정

  • page-size: Resource에서 읽어올 데이터 묶음 단위
  • chunk-size: 읽어온 데이터를 처리할 데이터 묶음 단위
    Page size = chunk size *n으로 구성하는 것이 좋고, 일반적으로는 page와 chunk 사이즈를 동일하게 구성합니다.
  1. 먼저, page 수 만큼 db 질의를 하여 데이터를 읽어옵니다
  2. Reader는 5000개를 질의하여 List를 가져오고, 한건씩 Processor에게 전달하여 줍니다
  3. 프로세서는 한건씩 데이터를 가공하고 5000건이 모이면 Writer에게 처리하여 줍니다.
  4. Writer를 청크사이즈만큼 일괄처리합니다.
  5. 1~4번 다시 수행
  6. data가 Null이 나올때까지 반복하여 줍니다.

Chunk-processing example

DB로부터 data를 조회할시에는 Reader로 DatabaseReader를 사용하게 됩니다. PagingItemReader, CursorItemReader 두 종류가 있습니다. 이 부분은 추후 포스팅으로 다시 정리하도록 하겠습니다

이번 포스팅에서는 baeldung 블로그에서 chunk 지향 Step에 대한 예를 가져왔습니다.
간략히 chunk 기반 시스템이 어떻게 구성되고 동작하는지만 알아보도록 하겠습니다.

@Configuration
@EnableBatchProcessing
public class ChunksConfig {

    @Autowired 
    private JobBuilderFactory jobs;

    @Autowired 
    private StepBuilderFactory steps;

    @Bean
    public ItemReader<Line> itemReader() {
        return new LineReader();
    }

    @Bean
    public ItemProcessor<Line, Line> itemProcessor() {
        return new LineProcessor();
    }

    @Bean
    public ItemWriter<Line> itemWriter() {
        return new LinesWriter();
    }

    @Bean
    protected Step processLines(ItemReader<Line> reader,
      ItemProcessor<Line, Line> processor, ItemWriter<Line> writer) {
        return steps.get("processLines").<Line, Line> chunk(2)
          .reader(reader)
          .processor(processor)
          .writer(writer)
          .build();
    }

    @Bean
    public Job job() {
        return jobs
          .get("chunksJob")
          .start(processLines(itemReader(), itemProcessor(), itemWriter()))
          .build();
    }
}
  • Job “chunksJob”이 실행됩니다
  • Job 내부에 start를 보면 독립적인 도메인은 Step을 호출합니다
  • Step “processLines“이 실행됩니다
  • processLines은 chunk 지향 Step으로 itemReader, itemProcessor, itemWriter로 구성되어 단계별로 실행됩니다.

참조

jojoldu님 블로그 - 6. Spring Batch 가이드 - Chunk 지향 처리
baeldung 블로그 tasklet vs chunk - Spring Batch - Tasklets vs Chunks | Baeldung
spring.batch.io - Configuring a Step

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

들어가며

SpringBatch를 처음 접하게 되면 아마 많은 분들이 이 문제를 겪지 않을까 생각합니다.

이 문제는 '지정된 Job이 아닌 모든 Job 실행' 입니다. 저도 최근에 Spring Batch를 접하며 겪은 문제이기도 합니다.
job name을 파라미터로 전해주었지만, 모든 Job들이 실행됩니다. 하지만, 우리는 모든 Job들이 동시간대에 실행되는 것을 원하지 않습니다.

그렇다면 어떻게 해결할 수 있을까요? 밑에서 바로 알아보도록 하겠습니다.


Job 구성

  1. Simple job
  2. Other Job
  3. application.yml

Simple Job 코드

@Slf4j
@RequiredArgsConstructor
@Configuration
public class SimpleJobConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job simpleJob() {
        return jobBuilderFactory.get("simpleJob")
            .start(simpleStep())
            .build();
    }

    @Bean
    public Step simpleStep() {
        return stepBuilderFactory.get("simpleStep")
            .tasklet((contribution, chunkContext) -> {
                log.info(">>>>> simple job started >>>>>");
                return RepeatStatus.FINISHED;
            })
            .build();
    }
}

Other Job 코드

@Slf4j
@Configuration
@RequiredArgsConstructor
public class OtherJobConfiguration {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job otherJob() {
        return jobBuilderFactory.get("otherJob")
            .start(otherStep())
            .build();
    }

    @Bean
    public Step otherStep() {
        return stepBuilderFactory.get("otherStep")
            .tasklet((contribution, chunkContext) -> {
                log.info(">>>>> other job started >>>>>");
                return RepeatStatus.FINISHED;
            })
            .build();
    }
}

applicatoin.yml

spring:
  profiles:
    active: local

---
spring:
  datasource:
    hikari:
      jdbc-url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
      username: sa
      password:
      driver-class-name: org.h2.Driver
  config:
    activate:
      on-profile: local

먼저, simpleJob, otherJob을 각각 생성하여 주고 yml을 설정하여 줍니다. 다음으로, Application의 argument를 다음과 같이 구성하여 줍니다.

--job.name=simpleJob version=1

job의 이름은 simpleJob이고 파라미터로 version=1을 주었습니다.
우리가 예상하는 결과는 console창에 ">>>>> simple job started >>>>>”이 찍히는 것입니다.

하지만, 예상과는 다르게 두개의 job이 실행되었습니다.
argument로 job.name을 전해주었지만
프레임워크 level에서는 어떠한 job이 실행되어야 하느지 알 수 없기에 모든 job을 실행하였습니다.


문제 해결

spring.batch.job.names: ${job.name:EMPTY}

이 문제를 해결하기 위해 yml에 위와 같은 property를 추가 해주도록 하겠습니다.


SpringBatch의 내부 BatchProperties 클래스를 들여다 보면 setNames 함수를 볼 수 있습니다.
위와 같이 정의된 job.names 값들을 Job으로 등록하여 줍니다. property를 yml에 추가하여 주고, 다시 실행해보도록 하겠습니다.

이제 원하는 Job이 정상적으로 실행되었습니다.

주의

여기서 argument로 job.names을 전달하지 않을 경우, 지정한 default EMPTY가 할당되게 됩니다.
즉, 이 소스상에서는 EMPTY로 할당된 Job이 없기 때문에 어떠한 Job도 실행되지 않습니다.

마무리

우리는 프로그램을 작성하며 Job을 하나만 작성하지 않습니다.
Server의 메모리 문제나, 실행되는 시간들이 다르기 때문에 일반적으로 Job이 나뉘어서 실행되기를 바랍니다.
따라서, yml에 해당 property 값을 적어주고 jar 실행시 적절한 argument를 전달하여 주면 됩니다!!


참조

jojoldu님 티스토리

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

Meta-Data Schema


아래의 테이블은 Spring Batch에서 제공하는 Meta-Data 테이블입니다.
해당 테이블들은 Batch Job의 실행을 기록하기 위해 존재합니다.

JobInstance   : BATCH_JOB_INSTANCE
JobExecution  : BATCH_JOB_EXECUTION
JobParameters : BATCH_JOB_EXECUTION_PARAMS
StepExecution : BATCH_STEP_EXECUTION
ExecutionContext : BATCH_JOB_EXECUTION_CONTEXT, BATCH_STEP_EXECUTION_CONTEXT
  • Spring Batch 메타 데이터 테이블은 Java로 표현하는 Domain 객체와 거의 일치합니다.
  • Java 객체(왼쪽)는 테이블(오른쪽)과 매핑됩니다.

위에 언급한 Java 도메인들은 전 포스팅에 언급하였기 때문에 이번 포스팅에선 설명을 생략하도록 하겠습니다.
이번 포스팅에서는 h2, mysql 데이터베이스 사용시 spring batch 설정방법과 meta 테이블의 prefix 설정방법에 대하여 알아보도록 하겠습니다.


Batch Job 설정, H2 실행

build.gradle -> dependency 설정

dependencies {
    compile('org.springframework.boot:spring-boot-starter-batch')
    compile('org.springframework.boot:spring-boot-starter-jdbc')
    runtime('com.h2database:h2')
    runtime('mysql:mysql-connector-java')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('org.springframework.batch:spring-batch-test')
}

DemoApplication.java 설정

@EnableBatchProcessing
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
  • @EnableBatchProcessing
    이 어노테이션을 선언하여 Spring Batch의 여러 기능들을 사용할 수 있게 합니다. 선언하지 않으면 Spring Batch 기능을 사용할 수 없기에 필수로 선언하여 줍니다.

SimpleJobConfiguration.java 설정

@Slf4j
@RequiredArgsConstructor
@Configuration
public class SimpleJobConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job simpleJob() {
        return jobBuilderFactory.get("simpleJob")
            .start(simpleStep())
            .build();
    }

    @Bean
    public Step simpleStep() {
        return stepBuilderFactory.get("simpleStep")
            .tasklet((contribution, chunkContext) -> {
                log.info(">>>>> job started >>>>>");
                return RepeatStatus.FINISHED;
            })
            .build();
    }
}
  • @Configuration안의 @Bean으로 Job과 Step을 등록하여 줍니다.
  • Step의 경우 tasklet과 ItemReader, ItemProcessor, ItemWriter로 나눌수 있는데 이번 포스팅에선 단순한 Step 실행을 위해 tasklet으로 실행하도록 하겠습니다.

application.yml 설정 (h2 기준)

spring:
  profiles:
    active: local

---
spring:
  datasource:
    hikari:
      jdbc-url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
      username: sa
      password:
      driver-class-name: org.h2.Driver
  config:
    activate:
      on-profile: local
---

profiles를 active로 설정하여 실행 해보도록 하겠습니다.

Job이 수행되는것을 확인하였습니다.


mysql 환경에서 실행하기

application.yml에 mysql 환경 추가해주기

---
spring:
  datasource:
    hikari:
      jdbc-url: jdbc:mysql://localhost:3308/spring_batch
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver
  config:
    activate:
      on-profile: mysql


Host, username, password를 각 db 환경에 맞추어 설정해주세요.
(저의 경우에는 docker를 이용하였습니다)

mysql에 batch ddl 생성하여 주기

IntelliJ 기준으로 ‘shift’ + ‘command’ + ‘o’를 이용하여 ‘schema-mysql.sql’의 내용들을 이용해 batch 테이블을 생성하여 줍니다.
h2와 mysql은 테이블 설정이 살짝 다르니, 꼭 mysql.sql 파일을 이용해 배치 테이블을 생성해주세요!!


profile을 설정한 후 실행하여 줍니다.


메타테이블에 방금 실행한 job의 정보가 기록 되었습니다. 이런식으로, spring batch는 트랜잭션을 프레임워크레벨에서 관리하여 주며 개발자가 비즈니스 로직 개발에 집중할 수 있게 도와줍니다.


메타 테이블 prefix 설정하기

일반적으로는 ‘batch_ ‘ 라는 prefix를 주어 메타테이블을 관리하지만, 여러가지 이유로 다른 prefixf를 주어 관리하기도 합니다. 예를 들면 많은 application이 하나의 batch 테이블을 사용하게 되면 메타 정보가 섞일 수 있기 때문에 다소 복잡도가 생길 수 있습니다.

BatchConfiguration.java

@Configuration
public class BatchConfiguration extends DefaultBatchConfigurer {

    private static final String TABLE_PREFIX = "CUSTOM_";

    private final DataSource dataSource;

    public BatchConfiguration(DataSource dataSource) {
        super(dataSource);
        this.dataSource = dataSource;
    }

    @Override
    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setTransactionManager(super.getTransactionManager());
        factory.setDataSource(dataSource);
        factory.setTablePrefix(TABLE_PREFIX);
        factory.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");
        return factory.getObject();
    }

    @Override
    protected JobExplorer createJobExplorer() throws Exception {
        JobExplorerFactoryBean factory = new JobExplorerFactoryBean();
        factory.setDataSource(dataSource);
        factory.setTablePrefix(TABLE_PREFIX);
        factory.afterPropertiesSet();
        return factory.getObject();
    }
}

DefaultBatchConfigurer 을 상속한 @Configuration을 하나 만들어 줍니다. 여기서 table prefix를 설정하여 줍니다. 저는 기존 ‘batch_’ prefix를 ‘custom_’ prefix로 설정하였습니다

다음으로 이전 mysql ddl script문을 이용하여 prefix 테이블을 새로 만들어 줍니다.

CREATE TABLE CUSTOM_JOB_INSTANCE  (
    JOB_INSTANCE_ID BIGINT  NOT NULL PRIMARY KEY ,
    VERSION BIGINT ,
    JOB_NAME VARCHAR(100) NOT NULL,
    JOB_KEY VARCHAR(32) NOT NULL,
    constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ENGINE=InnoDB;

CREATE TABLE CUSTOM_JOB_EXECUTION  (
    JOB_EXECUTION_ID BIGINT  NOT NULL PRIMARY KEY ,
    VERSION BIGINT  ,
    JOB_INSTANCE_ID BIGINT NOT NULL,
    CREATE_TIME DATETIME(6) NOT NULL,
    START_TIME DATETIME(6) DEFAULT NULL ,
    END_TIME DATETIME(6) DEFAULT NULL ,
    STATUS VARCHAR(10) ,
    EXIT_CODE VARCHAR(2500) ,
    EXIT_MESSAGE VARCHAR(2500) ,
    LAST_UPDATED DATETIME(6),
    JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
    constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
    references CUSTOM_JOB_INSTANCE(JOB_INSTANCE_ID)
) ENGINE=InnoDB;
... 중략

prefix를 설정한 테이블에 batch job 실행이 기록되었습니다.

이번 포스팅에선 job 기록을 위한 meta 테이블 생성을 알아보았습니다. Spring batch는 여러 커스터마이징 기능을 제공하는데 메타 테이블도 간단한 설정을 위와 같이 할 수 있습니다!!

다음 포스팅에서는 Step에 대해 자세히 알아보도록 하겠습니다.


참조

spring.io
jojoldu님 블로그

블로그 이미지

사용자 yhmane

댓글을 달아 주세요

Spring Batch를 들어가며

이커머스쪽 일을 하다 보니 자연스럽게 대용량 데이터를 다루어야 하는데, Batch 관련된 업무가 주를 이루게 되었다. 하지만, 4년차인 나는 아직도 삽질을 하고 있을뿐이고 주말에 시간을 내어 Batch 공부하려는데 Spring Batch 관련된 책이 안보인다. 왜 다 영어에, 출판한지 오래된것 뿐인지 ㅠㅠ 결국 Spring.io 문서를 보고 있는데 영어 너무 어렵잖아;;


SpringBatch Concept

Application을 운영하다 보면 미션 크리티컬 환경(Critical Environment)에서 비즈니스 운영을 수행하기 위해 대량 처리(Bulk Process)가 필요한 경우가 있다. 예를 들면 '은행 정산 업무', '재고 관련 정산 처리', '일단위 랭킹 계산' 등 많은 데이터를 처리해야 하는 경우가 있다.

이러한 업무에 대해서 스케줄링으로 특정 시간대에 작업을 진행하게끔 처리할 수 있다.
하지만, Spring Batch를 알게 되면 우리는 프레임워크의 도움을 받고 더욱 간결하게 비즈니스 로직 구현에 집중할 수 있다!!

  • Spring Batch는 다음과 같은 작업을 포함한다

    • 대용량 information의 복잡한 처리를 사용자 상호작용 없이 효과적으로 자동화 해준다 (월말 계산이나 정산)
    • 대용량 데이터의 반복되는 작업을 주기적(Periodcally)으로 처리
    • 내외부 시스템에 대용량 데이터를 통합하는데 사용합니다. 데이터 포맷팅, 유효성 검사 및 트랜잭션 처리에 유용
  • Spring Batch 주요 기능

    • 로깅, 추적, 트랜잭션 관리, 작업 처리, 재시작, 건너 뛰기등의 다양한 기능을 제공한다
    • 또한 파티셔닝 기술을 통해 대용량 및 고성능 배치 작업을 가능하게 한다

Spring Batch는 스케줄링 프레임 워크가 아닙니다. 스케줄러를 대체하는 것이 아니라 스케줄러와 함께 작동하기위한 것이다

컨셉에 대해 저도 오해(?)를 하였고 많은 분들이 헷갈려하는 것이 있는데,
"SpringBatch != Scheduling System"
위의 말대로 Batch는 Bulk Process를 프레임워크 레벨에서 유용하게 사용하게끔 지원하는 것입니다. 쿼츠의 다양한 스케줄링과는 다른 역할입니다!!


Spring Batch Domian

아래 다이어그램은 스프링 배치의 도메인 언어를 구성하는 핵심 개념을 나타내고 있다. 1:n부터 1:1의 관계로 이루어지는데 그림을 살펴보자.

Job은 1~n개의 step으로 이루어진다
각 step은 ItemReader, ItemProcessor, ItemWrite를 딱 한 개씩 가지며
각 Job은 JobLauncher가 실행하고, 현재 실행 중인 프로세스의 메타정보는 JobRepository에 저장된다

Job

Job은 전체 계층 구조에서 가장 상위에 있는 개념이고, XML 구성 파일 또는 Java 기반 구성과 함께 연결된다

Spring Batch에서 Job은 Step Instance들의 컨테이너이다. Job은 n개의 step들을 구성하고 job에 대하여 preventRestart, Listener, validation 등의 속성을 전역으로 설정할 수 있다. 아래는 샘플 코드이다.

@Bean
public Job footballJob() {
    return this.jobBuilderFactory.get("footballJob")
                     .start(playerLoad())
                     .next(gameLoad())
                     .next(playerSummarization())
                     .end()
                     .build();
}

footballJob을 실행하여 playerLoad, gameLoad, playerSummarization 의 Step들을 순차적으로 실행한다

위의 그림을 봐보자. 각 도표는 아래와 같은 것을 의미한다.

  • Job - ’EndOfDay’
  • JobParameter = 'schedule.data = 2007/05/05'
  • Job Instance = 'EndOfDay , 2007/05/05'
  • Job Execution = first attempt of Job 'EndOfDay, 2007/05/05'

Job Instance

Job 실행을 의미한다. Job Parameters에 상응하는 Job Instance는 하나 뿐이다. 여기서는 EndOfDay, 2007/05/05이다

Job Parameters

Job은 EndOfDay지만 Job Instance를 구별하기 위해서는 parameters가 필요하다.
여기서 사용하는 parameters가 job parameter이다. job을 참조하거나 식별하는 데이터로 사용한다

Job Execution

Job을 한번 실행했다는 의미이다. Job은 성공하거나 실패하게 되는데 그 정보가 메타테이블에 남게 된다.
Job이 실행 되었을경우 JobExecution은 매번 생성되지만, Job Instance는 실패한 파라미터로 재실행했을 경우에는 생성되지 않는다.


Step

Step은 Job의 독립적이고 순차적인 단계(step)를 모듈화한 객체이다.
따라서, 모든 Job은 하나 이상의 step으로 구성된다.
Step은 개발자의 재량으로 구현하기 때문에 단순한 업무부터 파일이나 DB의 배치 작업을 수행하게 된다.

Step Execution

JobExecution과 마찬가지로 Step을 한번 실행했다는 것을 의미한다.
이전 단계에서 Step이 실패했다면, 다음 Step Execution은 생성되지 않는다.
각 Execution은 실행/종료, read/rollback count 등의 정보들을 가지게 된다.


ExecutionContext

ExecutionContext는 framework에서 제어하는 key/value 쌍의 Collection으로 StepExeuction 또는 JobExecution에 상태를 저장한다.

배치 프레임워크가 주기적으로 커밋을 할때 Execution Context를 저장하기 때문에, ExecutionContext는 실패한 작업에 대하여 재시작을 할때 용이하다. 따라서, ItemReader에서 특정 키를 읽던중 실패하게 된다면, 재실행시 ExecutionContext에 그키를 집어넣어주면 된다. 나머지는 배치 프레임워크에서 작업을 처리하여 준다.


JobRepository

JobRepository는 모든 스테레오 타입에 대한 영속성(Persitence) 메커니즘이다.
또한 JobLauncher, Job, and Step 구현체에게 CRUD 기능을 제공한다.
Job이 처음 실행될때 레포지토리로부터 JobExecution이 획득되고, 실행중일때는 JobExecution, StepExecution에 구현체를 넘겨 저장한다


JobLauncher

JobLauncher는 JobRepository로부터 유효한 JobExecution 구현체를 얻고, Job을 실행한다


참조

Spring.io
godekdls.github.io
이동욱님의 tistory

블로그 이미지

사용자 yhmane

댓글을 달아 주세요