본문 바로가기

Batch

Spring Batch 를 Jenkins 를 이용해 간단하게 사용해보자

728x90

실무 맛보기

사진 출처 : 참고 블로그

실무에서는 어떻게 사용할까? 실무는 소프트웨어 개발 시 지속적 통합 서비스를 제공하는 툴인 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 또한 잘찍히는 것을 볼 수 있다.

crontab 참고 : Spring Scheduler


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 으로 연결확인 후 저장완료하면
다음과 같이 자신의 채널에 빌드 알림을 받을 수 있다.

728x90

'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