Spring-boot Batch Job

์žญ์žญ์ดยท2021๋…„ 4์›” 26์ผ
1

Spring-boot

๋ชฉ๋ก ๋ณด๊ธฐ
7/11
post-thumbnail

Spring-boot Batch Job

๐ŸŽ Contents

0. Summary

Spring-boot Batch Job ๊ด€๋ จ ๋‚ด์šฉ๋“ค์ด๋‹ค.

1. Metadata Table

Spring batch๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์ด ํ•„์ˆ˜๋กœ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์€ ์‚ฌ์šฉํ•˜๋Š” DB์—์„œ ํ…Œ์ด๋ธ”์กฐํšŒ๋ฅผ ํ†ตํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๊ฐ ํ…Œ์ด๋ธ”์˜ ์—ญํ• ์„ ์•Œ์•„๋ณด์ž.

  • BATCH_JOB_INSTANCE
    • Job Parameter์˜ ์ •๋ณด๊ฐ€ ์ €์žฅ๋œ๋‹ค.
    • ๋™์ผ Job์˜ Job Parameter๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฉด ๊ทธ๋•Œ๋งˆ๋‹ค BATCH_JOB_INSTANCE์— ์ƒ์„ฑ๋œ๋‹ค.
    • ๋™์ผํ•œ Job Parameter๋Š” ์—ฌ๋Ÿฌ ๊ฐœ ์กด์žฌํ•  ์ˆ˜ ์—†๋‹ค.

      Job Parameter๋Š” java -jar *.jar $PARAM=$VALUE ๋กœ ๋„ฃ์–ด์ค€๋‹ค.

  • BATCH_JOB_EXECUTION
    • BATCH_JOB_INSTANCE์˜ child ๊ด€๊ณ„
    • BATCH_JOB_INSTANCE์˜ ์„ฑ๊ณต/์‹คํŒจ์˜ ๋‚ด์—ญ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
  • BATCH_JOB_EXECUTION_PARAMS
    • BATCH_JOB_EXECUTION์ด ์ƒ์„ฑ๋  ๋‹น์‹œ ์ž…๋ ฅ๋ฐ›์€ Job Parameter๋ฅผ ๋‹ด๊ณ ์žˆ๋‹ค.

2. About JobBuilderFactory

Job์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” JobBuilderFactory์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

2.1. Syntax

  • start($STEP_METHOD)
    • $STEP_METHOD๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  • next($STEP_METHOD)
    • ์ˆœ์ฐจ์ ์œผ๋กœ step๋“ค์„ ์—ฐ๊ฒฐ์‹œํ‚ฌ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

2.2. Step for condition

์กฐ๊ฑด์— ๋”ฐ๋ผ ๋ถ„๊ธฐํ•˜์—ฌ ์„œ๋กœ ๋‹ค๋ฅธ step์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค.

  • ์˜ˆ์ œ์ฝ”๋“œ
@Bean
public Job stepNextConditionalJob(){
  return jobBuilderFactory.get("setpNextConditionalJob")
        .start(conditionalJobStep1())
          .on("FAILED") // if FAILED
          .to(conditionalJobStep3())  // step3๋กœ ์ด๋™
          .on("*")  // step3์˜ ๊ฒฐ๊ณผ์— ๊ด€๊ณ„ ์—†์ด
          .end()    // step3์œผ๋กœ ์ด๋™ ํ›„ flow ์ข…๋ฃŒ
        .from(conditionalJobStep1())  // step1๋กœ๋ถ€ํ„ฐ
          .on("*")  // FAILED์™ธ ๋ชจ๋“  ๊ฒฝ์šฐ
          .to(conditionalJobStep2())  // step2๋กœ ์ด๋™
          .next(conditionalJobStep3())  // step2 ์ •์ƒ ์ข…๋ฃŒ ํ›„ step3์œผ๋กœ ์ด๋™
          .on("*")  // step3์˜ ๊ฒฐ๊ณผ์— ๊ด€๊ณ„ ์—†์ด
          .end()
        .end()
        .build();
}
  • on()
    • catchํ•  ExitStatus์ง€์ •
  • to()
    • ์ด๋™ํ•  step ์ง€์ •
  • from()
    • ExitStatus์„ ๋ณด๊ณ  ์ด๋ฒคํŠธ ์บ์น˜
  • end()
    • on()๋’ค์— ์žˆ๋Š” end()๋Š” FlowBuilder๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • build()์•ž์— ์žˆ๋Š” end()๋Š” FlowBuilder๋ฅผ ์ข…๋ฃŒํ•œ๋‹ค.
  • Batch Status์™€ Exit Status๋Š” ๋‹ค๋ฅด๋‹ค.
    • Batch Status
      • Job๋˜๋Š” Step์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ Spring์—์„œ ๊ธฐ๋กํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” Enum
    • Exit Status
      • Step์˜ ์‹คํ–‰ ํ›„ ์ƒํƒœ
    • ExitStatus์˜ exitCode๋Š” Step์˜ BatchStatus์™€ ๊ฐ™๋‹ค.

3. Job Parameter, Scope

Spring Batch์—์„œ๋Š” ์™ธ/๋‚ด๋ถ€์—์„œ Job Parameter๋ฅผ ๋ฐ›์•„ Batch Component์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ง€์›ํ•œ๋‹ค.
Job Parameter๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„ , ํ•ญ์ƒ Spring Batch Scope๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค.

Spring Batch Scope๋Š” @StepScope์™€ @JobScope๋ฅผ ์ง€์นญํ•œ๋‹ค.

3.1. Usage Job Parameter

@Value("#{jobParameters[ํŒŒ๋ผ๋ฏธํ„ฐ๋ช…]}")

3.2. Usage Scope

@JobScope : Step์„ ์–ธ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.
@StepScope : Tasklet, ItemReader, ItemWriter, ItemProcessor์„ ์–ธ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

@Bean
public Job scopeJob() {
  return jobBuilderFactory.get("scopeJob")
          .start(scopeStep1(null))
          .next(scopeStep2())
          .build();
}

@Bean
@JobScope
public Step scopeStep1(@Value("#{jobParameters[requestDate]}") String requestDate) {
  return stepBuilderFactory.get("scopeStep1")
          .tasklet((contribution, chunkContext) -> {
            log.info(">>>>> This is scopeStep1");
            log.info(">>>>> requestDate = {}", requestDate);
            return RepeatStatus.FINISHED;
          })
          .build();
}

@Bean
public Step scopeStep2() {
  return stepBuilderFactory.get("scopeStep2")
          .tasklet(scopeStep2Tasklet(null))
          .build();
}

@Bean
@StepScope
public Tasklet scopeStep2Tasklet(@Value("#{jobParameters[requestDate]}") String requestDate) {
  return (contribution, chunkContext) -> {
    log.info(">>>>> This is scopeStep2");
    log.info(">>>>> requestDate = {}", requestDate);
    return RepeatStatus.FINISHED;
  };
}
  • scopeStep1(null), scopeStep2Tasklet(null)
    • Job Parameter ํ• ๋‹น์ด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰์‹œ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— null์„ ํ• ๋‹นํ•œ๋‹ค.

3.3. Scope and Bean

@StepScope๋Š” Step ์‹คํ–‰ ์‹œ์ ์— Bean์ด ์ƒ์„ฑ๋œ๋‹ค.
๋งˆ์ฐฌ๊ฐ€์ง€๋กœ @JobScope๋Š” Jop ์‹คํ–‰ ์‹œ์ ์— Bean์ด ์ƒ์„ฑ๋œ๋‹ค.
์ฆ‰, Bean์˜ ์ƒ์„ฑ ์‹œ์ ์„ ์ง€์ •๋œ Scope๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์œผ๋กœ ์ง€์—ฐ์‹œํ‚จ๋‹ค.

MVC์˜ request scope๊ฐ€ request/resoponse์— Bean์ด ์ƒ์„ฑ/์‚ญ์ œ๊ฐ€ ๋˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ JobScope. StepScope์—ญ์‹œ Job์ด ์‹คํ–‰๋˜๊ณ  ๋๋‚ ๋•Œ, Step์ด ์‹คํ–‰๋˜๊ณ  ๋๋‚ ๋•Œ ์ƒ์„ฑ/์‚ญ์ œ๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.

์ด ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ๊ฐ€์ง„๋‹ค.

  1. JobParameter์˜ Late Binding
    • Application ์‹คํ–‰ ์‹œ์ ์ด ์•„๋‹ˆ๋”๋ผ๋„ Controller๋‚˜ Service์™€ ๊ฐ™์€ ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ์—์„œ Job Parameter๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ๋™์ผ ์ปดํฌ๋„ŒํŠธ์˜ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ

4. Execute specific Job

๊ธฐ๋ณธ์ ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด์ง„ ๋ชจ๋“  job์ด ์‹คํ–‰๋œ๋‹ค.
์›ํ•˜๋Š” batch job๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค.

4.1. Update application.yml

Program arguments๋กœ job.name์ด ๋„˜์–ด์˜ค๋ฉด ํ•ด๋‹น ๊ฐ’๊ณผ ์ผ์น˜ํ•˜๋Š” job๋งŒ ์‹คํ–‰ํ•˜๋Š” ์˜ต์…˜

  • job.name์ด ์žˆ์œผ๋ฉด job.nameํ• ๋‹น, ์—†์œผ๋ฉด NONEํ• ๋‹น
spring.batch.job.names: ${job.name:NONE}

4.2. Execute

๋‹ค์Œ์€ Program arguments๋ฅผ ์„ ์–ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
java -jar *.jar --job.name=stepNextJob

4.3. How to use Job parameter

java -jar *.jar version=1 --job.name=stepNextJob

  • version=1
    • Job parameter
  • --job.name
    • application.yml์˜ job.name์— stepNextJob์ด๋ผ๋Š” ๊ฐ’์„ ํ• ๋‹นํ•ด์คŒ

5. Execute Job in Controller

๋งŒ์•ฝ ์™ธ๋ถ€์—์„œ ๋„˜๊ฒจ์ฃผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋”ฐ๋ผ Batch๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ์‹คํ–‰๋˜๋Š” ์˜ˆ์ œ์ด๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์›น์„œ๋ฒ„์—์„œ Batch๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š”๋‹ค.

@Slf4j
@RequiredArgsConstructor
@RestController
public class JobLauncherController {

  private final JobLauncher jobLauncher;
  private final Job job;

  @GetMapping("/launchjob")
  public String handle(@RequestParam("fileName") String fileName) throws Exception {

    try {
      JobParameters jobParameters = new JobParametersBuilder()
                              .addString("input.file.name", fileName)
                              .addLong("time", System.currentTimeMillis())
                              .toJobParameters();
      jobLauncher.run(job, jobParameters);
    } catch (Exception e) {
      log.info(e.getMessage());
    }

    return "Done";
  }
}

๋ชจ๋“  ์†Œ์Šค๋Š” ๊นƒํ—ˆ๋ธŒ์— ์˜ฌ๋ ค๋†“์•˜๋‹ค.
์ฐธ๊ณ ๋งํฌ: jojoldu ๋ธ”๋กœ๊ทธ

0๊ฐœ์˜ ๋Œ“๊ธ€