실무 맛보기
실무에서는 어떻게 사용할까? 실무는 소프트웨어 개발 시 지속적 통합 서비스를 제공하는 툴인 jenkins 를 이용해 spring-batch 를 실행한다.
보통 원격 Repository 와 Jenkins 를 연결해 Jenkins 에서 빌드후 실행하는 형식이 되지만, 지금은 devOps 에 대해 알아보는 시간이 아니니 간단하게 jenkins 에 spring-batch 프로젝트 jar 파일을 옮긴 후 Jenkins 의 scheduling 을 활용해 실행한 뒤, 결과를 slack 알림 서비스를 통해 받아보는 예제를 진행해 보겠다.
현재 부서의 프로젝트 또한 jenkins 를 활용해 spring-batch를 돌리고 slack 에 알림(jenkins가 진행하는 빌드에 대한 알림)을 받고있다.
(배치 성공 결과에 대한 slack 알림은 Jenkins 를 사용하지않고 JobListener 와 SlackAPI 를 사용하고 있음)
Spring 프로젝트를 만들자
먼저 Spring 프로젝트를 만들어 의존성을 추가해주자
Spring batch 는 상태관리를 위해 JobRepository 를 사용한다.이를 위해 데이터베이스 또는 인메모리 저장소가 필요하기에 h2에 대한 의존성또한 추가해주었다.
build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
}
이제 간단한 job 을 만들어보자. 여기서는 정말 간단하게 step 을 실행했는지 log 로 출력하는 정도로만 만들어보자.
@Configuration
@RequiredArgsConstructor
@Slf4j
public class MultiStepConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Bean
public Job exampleJob() {
return jobBuilderFactory.get("exampleJob")
.listener(new JobLoggerListener())
.start(startStep())
.next(nextStep())
.next(lastStep())
.build();
}
@Bean
public Step startStep() {
return stepBuilderFactory.get("startStep")
.tasklet((contribution, chunkContext) -> {
log.info("MultiStepConfig.startStep : {}", LocalDateTime.now());
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step nextStep(){
return stepBuilderFactory.get("nextStep")
.tasklet((contribution, chunkContext) -> {
log.info("MultiStepConfig.nextStep : {}", LocalDateTime.now());
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step lastStep(){
return stepBuilderFactory.get("lastStep")
.tasklet((contribution, chunkContext) -> {
log.info("MultiStepConfig.lastStep : {}", LocalDateTime.now());
return RepeatStatus.FINISHED;
})
.build();
}
}
Listener 를 만들자
@Slf4j
@Component
public class JobLoggerListener extends JobExecutionListenerSupport {
@Override
public void afterJob(JobExecution jobExecution) {
log.info("JOB 수행완료 {}", jobExecution);
if (jobExecution.getStatus().equals(BatchStatus.COMPLETED)) {
log.info("성공 슬랙 API");
} else {
log.info("실패 슬랙 API");
}
}
}
추가적으로 프로그램은 종료 시점에 exit code를 return 한다. Spring Boot 는 Exception 이 발생한 경우 Exit Code를 1로 , 정상적인 종료가 이루어지면 0을 return 하기에 이를 로그에 남기도록하자.
@Slf4j
@EnableBatchProcessing
@SpringBootApplication
public class DeeplifyBatchApplication {
public static void main(String[] args) {
int exit = SpringApplication.exit(SpringApplication.run(DeeplifyBatchApplication.class, args));
log.info("exit = {}", exit);
System.exit(exit);
}
}
추가적으로 Jenkins 는 기본포트가 8080 이기에 프로젝트의 포트를 바꿔주자.
application.properties
server.port=9090
이제 Spring 프로젝트의 코드작성은 끝났다. 다음의 명령어로 Spring 프로젝트를 빌드후 jar 파일을 만들자.
./gradlew clean build
jar 파일은 ./build/libs/~.jar 경로에 있을 것이다. 이를 기억해두자
Jenkins 설치
도커를 이용해 Jenkins 를 설치해보자
docker-compose.yaml
version: '3'
services:
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
volumes:
- ./jenkins:/var/jenkins_home
ports:
- "8080:8080"
jenkins가 관리할 서버 폴더를 쉽게 접근하기위해 현재 폴더에 jenkins 라는 폴더와 volumes 맵핑 시켜주도록했다.
다음 명령어로 이제 설치를 시작하고 띄워보자
docker-compose up -d
Jenkins 가 실행되고나서 아래에 나오는 써놓은 명령어로 jenkins 초기 비밀번호를 볼 수 있다. 이 값을 복사해 localhost:8080 에 접근해서 입력해주고, 계정생성 뒤 install suggested plugins
를 클릭해 필요한 plugin 들을 다운로드 받자
docker logs -f jenkins
여기까지 따라왔다면 이제 Jenkins 를 다룰 준비가 끝났다.
이제 다음의 과정을 진행하자.
아이템을 생성하자.
spring-batch 라는 이름으로 project 를 만들자.
생성된 프로젝트의 구성을 클릭하자.
먼저 jenkins 프로젝트의 폴더의 위치를 알기위해 Build 항목을 다음과 같이 세팅해주고 저장후, 빌드해보자
빌드 하고 나면 다음에서 프로젝트 위치를 확인할 수 있다.
그러면 확인한 경로에 우리가 아까 생성한 spring 프로젝트 jar 파일을 이동시키자. 참고로 jenkins 서버의 /var/jenkins_home
은 docker-compose 파일 만든 위치에 jenkins 폴더와 맵핑이 되어있기에 jenkins/workspace/spring-batch 하위에 이동시키면 된다.
그 후 다시 구성의 build 스크립트를 다음으로 변경하자
스크립트를 변경했다면 스케줄러를 설정할 것이다.
위쪽으로 살짝올라와 다음을 클릭한뒤 crontab 을 작성해주자(예제에서는 1분 단위로 실행되게 작성했다.)
*참고로 git 과 연결해 사용시 효과를 극대화 할 수 있는데, 여기서 `Build periodically` 는 crontab 주기마다 변경사항이 없어도 Build 를 실행하게되고, Poll SCM 은 crontab 주기마다 변경사항이 있을경우 Build 를 실행하게된다.*
일단 여기까지 진행후 저장한뒤 1분단위로 실행되는지 확인해 보자.
다음과 같이 1분 단위로 실행되는 것을 볼 수 있다.
빌드된것의 console 로 들어가면 우리가 출력하도록 한 log 또한 잘찍히는 것을 볼 수 있다.
Slack 알림으로 결과를 받아보자
알림을 받을 Slack WorkSpace 에서 더보기
를 클릭 후 앱
을 눌러 Jenkins
를 클릭해주자.
이제 안내되는 페이지 3단계에 다음을 잘 기억하자
Jenkins 에 Jenkins 관리 - 플러그인 관리로 들어가자
설치가능에서 Slack 을 검색후 설치하도록 하자. 설치가 다되면 메인페이지로 돌아가자.
이번에는 Jenkins 관리에서 Manage Credentials 에 들어가자
(global) 를 클릭하면 다음과 같이 Add Credentials 가 보인다. 클릭해주자
이후, Kind
옵션 secret text
선택 → Secret 항목에 통합 토큰 자격 증명 ID
입력 → ID 항목에 원하는 이름
입력 후 → OK 버튼을 클릭하자.
이제 아까 만들었던 spring-batch 프로젝트의 구성을 클릭해 빌드 후 조치
로 slack 을 클릭하자.
다음과 같이 설정 후 고급을 클릭하자.
Workspace 항목에는 팀 하위 도메인 값을 설정 → Credential 항목에는 우리가 이전에 만든 Secret Text 인 slack-notify 선택 → Channel / member id 항목에는 알림을 받을 채널명(ex: #테스트2)을 입력한다.
Test Connection 으로 연결확인 후 저장완료하면
다음과 같이 자신의 채널에 빌드 알림을 받을 수 있다.
'Batch' 카테고리의 다른 글
Spring Batch A 부터 Z 까지 (0) | 2022.07.08 |
---|---|
Quartz 사용해보기 (0) | 2022.04.25 |
Job 실습해보기 (0) | 2022.04.05 |
스프링 배치 스텝 Step (0) | 2022.04.04 |
스프링 배치 잡 Job (0) | 2022.04.04 |