관리 메뉴

나만의공간

Spring Batch #7(도메인 이해) 본문

IT/Spring Batch

Spring Batch #7(도메인 이해)

밥알이 2023. 10. 10. 09:09

Spring Batch에서 사용하고 있는 도메인들에 대한 개념 이해

Job

기본개념

  • 배치 계층 구조에서 가장 상위에 있는 개념으로 하나의 배치 작업을 의미 합니다.
  • Job Configuration을 통해 생성되는 객체로 배치 작업 구성을 어떡해 실행할 것인지 전체적으로 설정하고 설명해 놓은 객체 입니다.
  • 배치 Job을 구성하기 위한 최상위 인터페이스이며, 스프링 배치가 기본 구현체(SimpleJob, FlowJob)을 제공합니다.
    • SimpleJob
      • 순차적으로 Step을 실행시키는 Job
      • 가장 보편적이고 모든 Job에서 사용할 수 있는 표준 기능 제공
    • FlowJob
      • 특정 조건과 흐름에 따라 Step을 구성하여 실행시키는 Job
      • Flow 객체를 실행시켜서 작업을 진행
    • Job은 여러 Step을 포함하고 있는 컨테이너로서 반드시 한개 이상의 Step으로 구성

동작 과정 과 구조

  • Batch Job을 실질적으로 실행하는 주체는 JobLauncher 임.
  • Job을 실행시킬때 필요한 인자가 JobJobParameter 임.
  • JobLauncher에서 Job, Parameter를 인자로 받아 run함수를 호출하면 Job은 내부적으로 execute 메소드를 호출해서 각 Step을 실행합니다.

JobInstance

기본개념

  • Job이 실행될때 생성되는 Job의 논리적 실행 단위 객체고유하게 식별 가능한 작업 실행을 나타냅니다.
  • Job의 설정과 구성은 동일하지만 Job이 실행되는 시점에 처리하는 내용이 다르기 때문에 Job의 실행을 구분해야 합니다.
    • 하루에 여러번 수행되는 Job이 있다고 하면 각각의 Job은 JobInstance로 구분됩니다.
  • JobInstance 생성 및 실행
    • 처음 시작하는 Job & JobParameter일 경우 새로운 JobInstance를 생성
    • 이전과 동일한 Job & JobParameter로 실행할 경우 이미 존재하는 JobInstance를 리턴
      • 내부적으로 JobName & JobKey(JobParameter 해시값)을 통해서 존재하던 JobInstance를 구해 옴.
      • 이전 수행이 실패했을 경우에는 다시 수행이 가능, 이전 수행이 성공하면 다시 수행할 수 없음
        (중복 실행 방지)
  • Job : JobInstance 는 1:M 관계

BATCH_JOB_INSTANCE 테이블 매핑

JobName 과 JobKey(Parameter)가 동일한 데이터는 중복해서 저장할 수 없음
즉 JobInstance는 중복되지 않는 오직 유일한 하나의 값만 DB에 저장

  • JobLauncher가 Job과 JobParameter를 인자로 run 메소드를 호출함.
  • JobRepository를 통해 Job과 JobParameter를 얻어 DB로 부터 해당 값을 갖는 JobInstance가 존재하는지 여부를 확인
    • JobRepository: Job 실행중 발생하는 메타 데이터를 DB에 저장하는 역활 담당
  • 중복된 값이 없다면 새로운 JobInstance를 생성
  • 존재한다면 기존 JobInstance를 리턴, 이미 처리가 완료된 작업일 경우 예외가 발생함.

JobParameter

기본개념

  • Job을 실행할때 함께 포함된 파라미터를 가진 객체
  • 하나의  Job에 존재할 수 있는 여러개의 JobInstance를 구분하기 위한 용도
  • JobParameter와 JobInstance는 1:1 관계

생성 및 바인딩

  • 어플리케이션 실행시 주입 가능
    • java -jar sample.jar fromDate=20220101
  • 코드로 생성
    • JobParameterBuilder, DefaultJobParameterConverter 사용
  • SpEL(Spring Expression Language) 이용
    • @Value(#{jobParameter[fromDate]}")
    • @JobScope, @StepScope 선언 필수

BATCH_JOB_EXECUTION_PARAM 테이블 매핑

JOB_EXECUTION : BATCH_JOB_EXECUTION_PARAM 은 1:M관계

JobParameters는 JobParameter를 감싸고 있는 Wrapper 클래스 입니다.
내부적으로는 LinkedHashMap으로 구성되어 있고 value 값으로 JobParameter를 갖습니다.
JobParameter에는 파라미터 값(val)과 값에 대한 타입이 있습니다.

샘플코드

JobParameter를 세팅 하는 클래스

@Component
@RequiredArgsConstructor
public class JobParameterTest implements ApplicationRunner {

	private final Job job;
	private final JobLauncher jobLauncher;


	@Override
	public void run(ApplicationArguments args) throws Exception {
		// job 파라미터 생성
		JobParameters jobParameters = new JobParametersBuilder()
			.addString("name", "hello")
			.addLong("seq", 1L)
			.addDate("date", new Date())
			.addDouble("age", 26.5)
			.toJobParameters();

		// 잡 실행
		jobLauncher.run(job, jobParameters);
	}

}

JobParameter로 세팅된 정보 조회후 실행되는 Batch Job

@Slf4j
@Configuration
@RequiredArgsConstructor
public class HelloJobConfiguration {

	private final JobBuilderFactory jobBuilderFactory;
	private final StepBuilderFactory stepBuilderFactory;

	// 잡 구성
	@Bean
	public Job helloJob() {
		return jobBuilderFactory.get("helloJob")
			.start(helloStep1())
			.build();
	}

	// 스텝 구성
	@Bean
	public Step helloStep1() {
		return stepBuilderFactory.get("helloStep1")
			.tasklet(new Tasklet() {
				// 스텝이 하는 일 구성
				@Override
				public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
					JobParameters jobParameters = contribution.getStepExecution().getJobExecution().getJobParameters();

					// 파라미터가 잘 들어왔는지 확인
					Date date = jobParameters.getDate("date");
					Double age = jobParameters.getDouble("age");
					Long seq = jobParameters.getLong("seq");
					String name = jobParameters.getString("name");
					// String strAge = jobParameters.getString("age");
					log.info("date ={}", date);
					log.info("age ={}", age);
					log.info("seq ={}", seq);
					log.info("name ={}", name);
					// log.info("strAge ={}", strAge);

					return RepeatStatus.FINISHED;
				}
			})
			.build();
	}
}

JobExecution

기본개념

  • JobExecution은 JobInstance에 대한 한번의 시도를 의미하는 객체로서 Job 실행 중에 발생한 정보들을 저장하고 있는 객체
  • 시작시간, 종료시간, 상태(시작, 완료, 실패), 종료상태의 속성을 가짐
  • Job이 실행되면, JobInstance는 JobParameters가 동일하면 단 한번만 실행 됨.
  • JobExecution은 JobInstance가 실행될 때 마다 생성됨

JobExecution 과 JobInstance와의 관계

  • JobExecution은 'FAILED' 또는  'COMPLETED'등의 Job의 실행 상태를 갖고 있음.
  • JobExecution의 실행 상태 결과가 'COMPLETED'면 JobInstance 실행이 완료된 것으로 간주하여 재실행이 불가능함
  • JobExecution의 실행 상태가 'FAILED'면 JobInstance 실행이 완료되지 않은 것으로 간주해서 재실행이 가능함
    • JobParameters가 동일한 값으로 Job을 실행할지라도 이전의 JobExecution이 실패했기 때문에 기존의 JobInstance에서 새로운 JobExecution을 생성하여 실행이 이뤄짐
      • JobParameters가 동일한 값으로 Job을 실행할지라도 이전의 JobExecution이 실패하면 새로운 JobExecution 실행

BATCH_JOB_EXECUTION 테이블 과 매핑

JobInstance 와 JobExecution은 1:M 관계로서 JobInstance에 대한 성공/실패 내역을 갖고 있음.

STEP

기본 개념

  • Batch Job을 구성하는 독립적인 하나의 단계로서, 실제 배치 처리를 정의하고 컨트롤하는데 필요한 모든 정보를 가지고 있는 도메인 객체
  • 단순한 단일 태스크뿐 아니라 입력과 처리 그리고 출력과 관련된 복잡한 비즈니스 로직을 포함하는 모든 설정들을 담고 있습니다.
  • 모든 Job은 하나 이상의 Step으로 구성됩니다.

기본 구현체

  • TaskletStep
    • 가장 기본이 되는 클래스로서 Tasklet 타입의 구현체들을 제어합니다.
  • PartitionStep
    • 멀티 스레드 방식으로 Step을 여러 개로 분리해서 실행합니다.
  • JobStep
    • Step 내에서 Job을 실행합니다.
  • FlowStep
    • Step 내에서 Flow를 실행합니다.

STEPEXECUTION

기본 개념

  • Step에 대한 한 번의 시도를 의미하는 객체로서 Step 실행 중에 발생한 정보들을 저장하고 있는 객체
    • 시작시간, 종료시간, 상태, commit count, rollback count 등의 속성을 갖습니다.
  • Step이 매번 시도될 때마다 새로 생성 되며 각 Step 별로 생성 됩니다.
  • Job이 실패되어 재시작될 경우 이미 성공적으로 완료된 Step은 재실행되지 않고 실패한 Step만 실행됩니다.
    • 모두 재시작 할 수 있는 옵션도 존재합니다.
  • 이전 단계 Step이 실패해서 현재 Step을 실행되지 않았다면 StepExecution은 생성되지 않습니다.
  • JobExecution과의 관계
    • Step의 StepExecution이 모두 정상적으로 완료되야만 JobExecution이 정상적으로 완료됩니다.
    • Step의 StepExecution 중 하나라도 실패하면 JobExecution은 실패합니다.

BATCH_STEP_EXECUTION 테이블과 매핑

  • JobExecution과 StepExecution은 1:M 관계
  • 하나의 Job에 여러 개의 Step으로 구성됬을 경우 각 StepExecution은 하나의 JobExecution을 부모로 갖습니다.

STEP CONTRIBUTION

기본 개념

  • 청크 프로세스의 변경 사항을 버퍼링 한 후 StepExecution 상태를 업데이트하는 도메인 객체
    • 쉽게 말하면, Step에서 정의한 일들을 처리한 결과들을 저장해두다가 StepExecution에 업데이트 하는 일을 말합니다.
  • 청크 커밋 직전에 StepExecution의 apply 메서드를 호출하여 상태를 업데이트합니다.
  • ExitStatus의 기본 종료코드 외 사용자 정의 종료코드를 생성해서 적용할 수 있습니다.

EXECUTION CONTEXT

기본 개념

  • 프레임워크에서 유지 및 관리하는 "키-값"으로 된 컬렉션으로 StepExecution 또는 JobExecution 객체의 상태(필드값들)을 저장하는 공유 객체
  • DB에 직렬화 한 값으로 저장됩니다.("key":"value")
  • 공유 범위
    • Step 범위 : 각 Step Execution에 저장되며 Step 간 서로 공유 불가능
    • Job 범위 : 각 Job의 Execution에 저장되며 Job간 서로 공유는 되지 않지만, 해당 Job에 속한 Step은 공유 가능
  • Job 재시작시 이미 처리한 Row 데이터는 건너뛰고 이후부터 수행하도록 상태 정보를 활용합니다.

아래 코드를 이용하여 Context값들을 꺼내서 사용할수 있습니다.

public class ExecutionContextTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        ExecutionContext jobExecutionContext = contribution.getStepExecution().getJobExecution().getExecutionContext();
        ExecutionContext stepExecutionContext = contribution.getStepExecution().getExecutionContext();

        ExecutionContext jobExecutionContext2 = chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext();
        ExecutionContext stepExecutionContext2 = chunkContext.getStepContext().getStepExecution().getExecutionContext();
        return RepeatStatus.FINISHED;
    }
}

 

JobRepository

기본 개념

  • 배치 작업 중의 정보를 저장하는 저장소 역할
  • Job이 언제 수행되었고, 언제 끝났으며, 몇 번이 실행되었고 실행에 대한 결과 등의 배치 작업의 수행과 관련된 모든 메타 데이터를 저장합니다.
    • JobLauncher, Job, Step 구현체 내부에서 CRUD 기능을 처리합니다.
    • 실행 과정에서 데이터를 DB에 저장하고, 필요한 데이터는 읽어오는 작업을 하는 객체라고 보면 됩니다.

JobLauncher

기본 개념

  • 배치 Job을 실행시키는 역할
  • Job과 Job Parameters를 인자로 받아 배치 작업을 수행한 후 최종 client에게 JobExecution을 반환합니다.
  • 스프링 부트 배치가 구동되면 JobLauncher 빈이 자동 생성 됩니다.
  • Job 실행
    • JobLauncher.run(job,jobParameters)
    • 스프링 부트 배치에서는 jobLauncherApplicationRunner가 자동적으로 JobLuancher을 실행시킵니다.
    • 동기적 실행
      • taskExecutor를 SyncTaskExecutor로 설정한 경우(기본값)
      • JobExecution을 획득하고 배치 처리를 최종 완료한 이후 Client에게 JobExecution을 반환
      • 스케줄러에 의한 배치처리에 적합(배치처리시간이 길어도 무관한 경우)
    • 비동기적 실행
      • taskExecutor가 SimpleAsyncTaskExecutor로 설정할 경우
      • JobExecution을 획득한 후 Client에게 바로 JobExecution을 반환하고 배치처리를 진행
      • HTTP 요청에 의한 배치처리에 적합(배치처리 시간이 길 경우 응답이 늦어지지 않도록 함)
Comments