욱'S 노트

Spring Batch - 메타데이터 이용 본문

Programming/Spring Batch

Spring Batch - 메타데이터 이용

devsun 2015. 1. 22. 16:54



JobLauncher는 새로운 JobExecution을 생성하기 위해 JobRepository를 이용한다. 작업 수행중에 같은 실행을 업데이트하기 위해 같은 JobRepository를 이용한다. 단순한 시나리오는 위와 같지만,  수백 개의 배치 작업과 스케쥴링 요구 사항을 충족하기 위해선 다음과 같이 요구된다.



JobExplorer와 JobOperator는 메타데이터에 대한 쿼리와 컨트롤을 추가한 인터페이스이다.


JobExplorer


기존의 실행을 리파지토리로부터 쿼리를 하는 것이 가장 기본적인 기능일 것이다. 이러한 기능은 JobExplorer 인터페이스에 의해 제공된다. JobExplorer는 JobRepository의 read-only 버젼이다. 팩토리빈에 의해 쉽게 정의할 수 있다.

<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
p:dataSource-ref="dataSource" p:tablePrefix="BATCH_"/>`


JobRegistry


JobRegistry는 반드시 정의해야 되는 것은 아니다. 그러나 해당 컨텍스트에서 이용가능한 작업목록을 유지하고 싶을때 유용하다. 프레임웍은 오직 하나의 구현체만을 제공하고 단순한 맵 형태로 제공된다. 다음과 같이 정의할 수 있다.

<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry"/>

JobRegistry를 자동적으로 저장시키는 방법은 두가지가 있다. 하나는 bean post processor를 이용하는 것이고, 다른 하나는 registrar lifecycle component를 이용하는 것이다.


모든 작업을 등록하는 bean post-processor의 정의는 다음과 같다.

<bean id="jobRegistryBeanPostProcessor" class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>

AutomaticJobRegistrar는 child context를 생성하고 작업을 생성하는 lifecycle component이다. 이렇게 할 경우 하나의 이점은 child 컨텍스트에 작업명은 전체 registry 유일하게 식별할 수 있어야 하지만 디펜던시 들은 자연스러운 이름을 사용할 수 있다는 것이다. 예를 들어 작업마다 xml configuration을 만들었다고 가정을 해보자. 각 작업마다 ItemReader를 가질 것이다. 거기에  "reader"라는 같은 이름은 빈들이 정의되어 있다고 할 때, 이들이 같은 context에 있다면 crash가 나거나 override가 되지만 이 경우에는 자동적으로 그러한 상황을 피할 수 있게 된다.

<bean id="JobRegistrar" class="org.springframework.batch.core.configuration.support.AutomaticJobRegistrar">
<property name="applicationContextFactories">
<bean class="org.springframework.batch.core.configuration.support.ClasspathXmlApplicationContextsFactoryBean">
<property name="resources" value="classpath*:/config/job*.xml"/>
</bean>
</property>
<property name="jobLoader">
<bean class="org.springframework.batch.core.configuration.support.DefaultJobLoader">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>
</property>
</bean>

Registrar는 두가지 필수적인 프로퍼티를 가지는데, 하나는 ApplicationContextFactory의 배열이고 다른 하나는 JobLoader이다. JobLoader는 child 컨텍스트의 라이프사이클을 관리하고 JobRegistry에 작업을 등록한다.


JobOperator


JobRepository는 메타데이터에 대한 CRUD 기능을 제공하고, JobExplorer는 메타데이터에 대한 read-only 기능을 제공한다고 하였다. 하지만 이러한 기능들은 공통적인 모니터링 task는 즉, 중지, 재시작 또는 작업 요약등과 같은 배치 수행과 같이 사용되었을 때, 더욱 유용하다. JobOperator에 그러한 기능들을 스프링 배치에서 제공한다. 간단한 정의는 다음과 같다.

<bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator">
<property name="jobRegistry" ref="jobRegistry"/>
<property name="jobRepository" ref="jobRepository"/>
<property name="jobExplorer" ref="jobExplorer"/>
<property name="jobLauncher" ref="jobLauncher"/>
</bean>

JobParametersIncrementer


대부분은 JobOperator 메소드는 명백하고 javadoc를 보면 자세한 설명을 찾을수 있다. 하지만 startNextInstance메소드는 설명을 할 필요가 있다. 이 메소드는 작업의 새로운 작업 인스턴스를 시작한다. JobExecution에 심각한 문제가 있다면 이러한 기능은 꼭 필요하다. 이러한 경우 작업은 처음부터 다시 실행되어야 할 필요가 있을 것이다. 새로운 JobInstance를 수행하기 위해서 새로운 JobParameter가 필요하다. 이러한 경우 startNextInstance 메소드는 작업에 대해서 강제로 JobInstance를 새로 생성하기 위해서 JobParametersIncrementer를 사용한다. 다음은 간단한 JobParamtersIncrementer를 작성하고 설정한 예이다.

public class SimpleJobParametersIncrementer implements JobParametersIncrementer {
@Override
public JobParameters getNext(JobParameters parameters) {
if (parameters==null || parameters.isEmpty()) {
return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters(); }
long id = parameters.getLong("run.id",1L) + 1;
return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
}
}

<batch:job id="job1" parent="baseJob" incrementer="sampleIncrementer">
<step id="step1" parent="standaloneStep"/>
<batch:listeners merge="true">
<batch:listener ref="listenerTwo"/>
</batch:listeners>
</batch:job>

Stopping a job


JobOperator에 작업 중지를 요청했을때, 즉시 강제로 shutdown하는 방법은 없기 때문에 shutdown은 바로 일어나지 않는다. 특히 현재 비즈니스 로직과 같은 개발자의 코드를 수행하고 있을 경우에는 더 그렇다. 이러한 경우 프레임워크가 컨트롤할 수 있는 영역이 아니기 때문이다. 하지만 컨트롤 할 수 있는 최대한 빠른 시점에 현재 StepExecution을 STOPPED 시킬 것이고 JobExecution에서 해당 상황을 전달 할 것이다.


Aborting a job


작업 수행이 실패하였다면 재시작될 수 있다. 그러나 작업의 상태가 ABANDONED라면 작업은 재시작할 수 없다. ABANDONED 상태는 작업 재시작을 스킵하기 위해서 사용할 수도 있다. 만약 프로세스가 죽어버렸다면 JobRepository는 해당 상태가 FAILED인지 ABANDONED인지 알 수가 없다. 이러한 경우에는 비즈니스 적인 의사 결정이 필요하며, 강제로 상태를 세팅해야 된다. 스프링 배치 어드민 JobService에 해당 기능이 제공된다.

Comments