-
Jobrunr 사용한 Springboot에 스케줄링 작업 구현Spring Boot 2025. 1. 30. 00:20
배경
- Spring Scheduler는 간단하지만 실패시 처리/실행 로그 확인 같은 작업이 굉장히 불편하다.
- Jobrunr를 사용하면 Spring Scheduler의 불편함을 해결할 수 있다.
- 별도 구축없이 내장 dashboard를 제공 (실패/성공 이력 모니터링 가능, 스케줄링 삭제, 재시도 가능)
- 애너테이션 기반 내장 스케줄링 지원 (@Recurring)
- API 기반 작업 등록 지원 (enqueue, scheduleIn, schedulerRecurrently)
- 실패 시 재시도, 부가처리 가능
- 사용 방법이 간단하여 spring batch 처럼 많은 공부를 필요로 하지 않는다. (Java 8 문법만 알면 이해 가능하다.)
- 공식 문서 : https://www.jobrunr.io/en/documentation/
Jobrunr란?
- 백그라운드 처리를 위한 Java Open Source 라이브러리이다.
- persistent storage 기반으로 동작하며 Spring Batch, Quartz, Java CRON scheduler를 대체한다.
- 2020년 만들어져 올해로 5년 되었다.
Jobrunr 아키텍처
- Persistent storage 기반으로 동작한다.
- 요약하자면 Persistent storage(ex. MySQL, Redis, MongoDB, DynamoDB, H2 . . .)를 Queue처럼 사용해, 실행할 작업(Job)을 저장하고, 백그라운드에서 Job 처리 후 storage 상태 관리 방식으로 동작한다.
- Fire-and-Forget 방식으로 동작한다.
- Kafka나 RabitMQ 같은 Pub/Sub 구조에서 메시지 발행하고 응답은 처리 안하는 것 처럼, 작업을 Persistent storage에 저장하고 저장된 작업은 백그라운드에서 실행하고 상태를 관리하는 것이 기본 동작이다.
- 백그라운드 작업은 기본 128개 스레드(virtual thread 지원)에서 Queue된 작업의 백그라운드 실행을 지원한다.
Persistent storage
- 저장소는 RDB, NoSQL 모두 지원한다.
- 프로젝트를 실행하면 DB에 아래의 기본 테이블이 생성된다.
+------------------------------+ | Tables_in_mydatabase | +------------------------------+ | jobrunr_backgroundjobservers | | jobrunr_jobs | | jobrunr_jobs_stats | | jobrunr_metadata | | jobrunr_migrations | | jobrunr_recurring_jobs | +------------------------------+
- jobrunr_backgroundjobservers : 작업 수행할 worker 서버 정보 저장 (분산 환경이면 N대도 가능하다.)
- jobrunr_jobs : 실행 작업(job) 저장
- jobrunr_jobs_stats : 작업 상태 통계
- jobrunr_recurring_jobs : 반복주기로 설정된 스케줄링 작업 저장
- jobrunr_migrations : 버전 관리
- jobrunr_metadata : 메타 데이터 저장
Scheduling 작업 실행 해보기
설정 방법은 예제 코드 참고 : https://github.com/sendkite/jobrunr
@Recurring
- 특정 job을 주기적으로 실행하기 위해서 @Recurring를 사용한다.
- 실행 주기는 cron 표현식으로 지정한다.
- zoneId는 cron 표현식을 해석할 때 사용할 시간대를 지정한다.
- 주기는 실행 시간보다 짧으면 안된다.
- 로그에 다음과 같이 찍히며 n번 job 실행됨 (...this means a long gc happened and jobrunr is catching up ...)// 자동 1분마다 실행되는 Job @Recurring(id = "daily-resupply", cron = "0 * * * * *", zoneId = "Asia/Seoul") public void resupply(JobContext jobContext) throws InterruptedException { JobDashboardProgressBar jobDashboardProgressBar = jobContext.progressBar(stockLocations.size()); logger.info("Resupplying stock locations - {}", stockLocations); for(String stockLocation : stockLocations) { orderFulfillmentService.resupply(stockLocation); jobDashboardProgressBar.increaseByOne(); jobContext.logger().info(String.format("Resupplied stock %s", stockLocation)); } } // 수동 jobScheduler.scheduleRecurrently("every-minute-job", Cron.everyMinute(), () -> System.out.println("🚀 1분마다 실행되는 Job!"));
reference
- 공식문서 : https://www.jobrunr.io/en/.
- 제작자의 10분 설명 : https://www.youtube.com/watch?v=hzeBa6FWf7E.
- 2024 SpingDeveloper 튜토리얼 : https://www.youtube.com/watch?v=e9POHS0BjEg
반응형'Spring Boot' 카테고리의 다른 글
[springboot 예외 처리 안티패턴 정리] Exception Handling Worst Practice (13) 2024.12.30 Lombok 사용시 주의점 (쓰지 말아야 할 Lombok) (3) 2024.11.12 springboot 애플리케이션 데이터베이스 초기화 (1) 2024.11.08 스프링 개발자가 가장 많이하는 실수 (0) 2024.06.19 Port Adapter 패턴이란? (클린아키텍처) (1) 2024.04.20