작성
·
1.3K
1
안녕하세요, 강사님
@Slf4j
@RequiredArgsConstructor
@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {
@Override
public JobLauncher createJobLauncher() throws Exception {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(1);
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(500);
taskExecutor.afterPropertiesSet();
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setTaskExecutor(taskExecutor);
jobLauncher.setJobRepository(createJobRepository());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
//...
}
공통으로 Job 관리할때는 JobLauncher에 ThreadPoolTaskExecutor을 등록해서 대기작업을 했습니다.
만약 엑셀 가져오기(업로드), 통계배치 등 배치Job 종류가 여러개이고 따로 관리해야할때,
엑셀 pool 2개, 통계배치pool 1개 이렇게 따로 pool 을 만들고 싶다면, 어떻게 해야할까요?
Job 종류 마다 JobLauncher 을 여러개 만들어야 하는건가요?
pool 개수 이상에 요청이 들어오면 대기상태였다가 앞의 배치 작업 끝나면 실행시키는 방식을 생각하고 있습니다.
ex. 엑셀 pool 2개, 통계배치pool 1개 일 경우
엑셀가져오기 작업 요청이 3번 들어오면 앞의 두 작업은 실행되고 나머지 하나는 대기상태.
동시에 다른 통계배치작업 요청이 2번 들어오면 앞의 한 작업은 실행되고 나머지 하나는 대기상태.
답변 1
0
네
스프링 배치에서 JobLauncher 는 초기화시 빈의 형태로 생성이 됩니다.
정확하게는 프록시 객체로 생성이 되고 프록시가 실제 타겟을 호출하는 식으로 이루어집니다.
이 때 프록시가 빈이 된다고 보시면 됩니다.
즉 기본적으로 JobLauncher 는 프록시 빈 한 개가 생성되어 여러 Job 에서 공유하게 됩니다.
그리고 스프링 부트에서는 빈으로 등록된 모든 Job 을 순서대로 실행시키는데 이것을 JobLauncher 에게 위임해서 TaskExecutor 가 처리하도록 합니다.
이 말 즉 슨 Job 의 종류나 역할에 상관없이 JobLauncher 와 TaskExecutor 가 모든 Job 을 동기 혹은 비동기로 실행하게 됩니다.
특히 스프링 부트 배치에서는 자동설정 기능에 의해 JobLauncherApplicationRunner 가 모든 Job 을 JobLauncher 에 강제로 전달해 버리기 때문에 Job 의 종류에 따라 JobLauncher 를 다르게 선택하거나 TaskExecutor 를 구분해서 실행하도록 컨트롤 할 수는 없을 것 같습니다.
그래서 질문 하신 내용대로 처리가 이루어질려면 빈으로 등록된 Job 들 중에서 원하는 Job 을 DI 받고 하나의 JobLauncher 와 TaskExecutor 를 공유하는 것이 아닌 Job 마다 독립적으로 생성 및 할당해서 적용되도록 구성해야 할 것 같습니다.
그리고 TaskExecutor 변수가 멤버 변수이기 때문에 런타임 시점에 TaskExecutor 구현체를 JobLauncher 에 전달해서 적용하는 전략패턴을 쓰면 Job 마다 Pool 의 설정을 독립적으로 가져 갈 수 없는 문제가 발생해서 이것도 해결책은 될 수 없습니다.
만약 Job 마다 별도의 jar 로 만들어 사용한다면 하나의 JobLauncher 를 사용하고 TaskExecutor 만 변경하도록 할 수 있을 것 같습니다.
리플렉션을 사용한다면 배치를 실행할 때 TaskExecutor 의 구현클래스 풀네임을 실행 인자로 전달해서 동적으로 클래스를 로드하고 객체를 만들어 JobLaucher 에 전달해서 사용하도록 할 수 도 있는데 코드가 복잡해 질 수 있고 그리 추천할 만한 방법은 아닙니다.
혹 다른 방법이 있는지 저도 계속 고민해 보겠습니다.^^