티스토리 뷰
Spring 스케줄러 (ThreadPoolTaskScheduler)를 이용한 동적 스케줄 관리 적용기 (2) - 로그 관리 (이벤트 리스너)
광돌ol 2024. 10. 20. 23:37들어가기전
이전 글에서는 Spring 스케줄러에 대한 사용 이유와 개념 정리 적용하기 등을 해보았습니다. 이번 글에서는 간단하게 스케줄에 대한 로그를 작성하기 방법에 대해서 정리하고자 합니다.
Spring 스케줄러에 대한 기본 개념 정리는 아래 링크를 참고하세요.
Spring 스케줄러의 단점
Quartz 스케줄러와 다르게 세세한 실행 기록을 남기는 것이 어렵습니다. Quartz에서는 JobListener를 통해 배치 실행 전, 중, 후 등에 대한 세세한 컨트롤이 가능하지만 Spring 스케줄러는 경량성 스케줄러이기 때문에 세세한 컨트롤은 어렵다는 것이 단점에 해당합니다.
만약 스케줄 실행 과 완료 시점에 대한 로그를 작성하려면 어떻게 하면 좋을까요?
스케줄러 실행에 대한 기록을 간단하게 남기고 싶은데 어떻게 하면 좋을까?에 대해 고민해봤습니다.
간단하게 생각해봤을때 스케줄러에 대한 실행 시점과 완료 시점에 대한 기록만 남기고 싶다면 스케줄러 실행하는 부분에 로그 등록 부분만 넣어주면 되지 않을까?라는 생각을 해보았습니다. 하지만 단순히 로그를 insert만 하기 보단 ApplicationEventPublisher 을 이용하여 이벤트를 적용하는 식을 처리하여 스케줄러 실행에 딜레이가 발생하지 않을 수 있도록 처리하고자 했습니다.
ApplicationEventPublisher란 무엇인가?
Spring Framework에서 이벤트를 발생시키는 인터페이스로, 애플리케이션 내에서 커스텀 이벤트나 시스템 이벤트를 다른 컴포넌트에 비동기적으로 전달할 수 있도록 하는 역할을 합니다. 이를 통해 애플리케이션 내에서 서로 다른 컴포넌트 간의 통신을 느슨하게 유지하면서 이벤트 기반 프로그래밍 모델입니다.
즉, 애플리케이션 내에서 발생한 특정 이벤트를 다른 컴포넌트에 비동기적으로 전달하여 느슨한 결합을 유지하면서 통신할때 사용한다는 말입니다.
ApplicationEventPublisher를 선택한 이유
저는 스케줄러를 통해 실행되는 시점에 로그를 등록처리할 때 비동기적으로 처리하고자 했습니다. 왜냐하면 로그와 같이 동기로 돌아가게 되면 한 Thread에서 순서대로 실행되기에 스케줄러 실행에 대한 시간적인 명확성이 떨어질 수 있을 거라 보았습니다 그래서 별도로 돌아 처리하는 것이 더욱 정확성이 높을 거라 생각했습니다.
로그 설정하기
1.스케줄러 로그 엔티티 생성
- 스케줄러 로그에 대한 테이블을 생성합니다.
@Entity
public class CmsScheduleLog {
...
public CmsScheduleLog(Long configId, String status, String startTime, String endTime, String message) {
this.configId = configId;
this.status = status;
this.startTime = startTime;
this.endTime = endTime;
this.message = message;
}
}
2. ScheduleEvent 객체 생성
- 이벤트를 실행에 적용할 객체를 생성합니다.
public class SchedulerTaskEvent extends ApplicationEvent{
private Long id;
private String status;
private String startTime;
private String endTime;
private String message;
}
3. SchedulerTaskEventListener 이벤트 클래스 생성
public class SchedulerTaskEventListener {
private final SchedulerLogRepository schedulerLogRepository;
@Async
@EventListener
public void handleEvent(SchedulerTaskEvent event) {
LOGGER.info(" scheduling event source : {}",event.getSource());
CmsScheduleLog cmsScheduleLog = new CmsScheduleLog(
event.getId(),
event.getStatus(),
event.getStartTime(),
event.getEndTime(),
event.getMessage()
);
LOGGER.info(" scheudler log : "+cmsScheduleLog.toString());
schedulerLogRepository.save(cmsScheduleLog);
}
}
위 코드와 같이 handleEvent 메소드를 생성하고 @EventListener를 선언하여 이벤트 리스너임을 선언합니다.
파라미터로는 SchedulerTaskEvent를 선언하여 해당 객체에 대한 이벤트임을 알려줍니다. 그리고 @Async를 선언하여 비동기처리를 하여 느슨한 통신 처리를 해줍니다.
4. 스케줄러 로그 적용
@Service
public class CmsSchedulerService {
....
private final ApplicationEventPublisher eventPublisher;
...
public void scheduleTask(CmsScheduleConfig scheduleConfig) throws Exception {
Object bean = applicationContext.getBean(scheduleConfig.getBeanName());
Method method = bean.getClass().getMethod(scheduleConfig.getMethodName());
ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(() -> {
System.out.println("#### taskScheduler schedule #### ");
long startTime = System.currentTimeMillis();
eventPublisher.publishEvent(new SchedulerTaskEvent(
this,
scheduleConfig.getIdx(),
"START",
startTime+"",
"",
scheduleConfig.getTitle() + " 스케줄링 시작"
));
try{
method.invoke(bean);
long endTime = System.currentTimeMillis();
eventPublisher.publishEvent(new SchedulerTaskEvent(
this,
scheduleConfig.getIdx(),
"COMPLETE",
"",
endTime + "",
scheduleConfig.getTitle() + " 스케줄링 완료"
));
}catch (Exception e) {
eventPublisher.publishEvent(new SchedulerTaskEvent(
this,
scheduleConfig.getIdx(),
"ERROR",
startTime+"",
"",
scheduleConfig.getTitle() + " 스케줄링 실패 원인 : "+e.getMessage()
));
}
},new CronTrigger(scheduleConfig.getCrontab()));
scheduledTasks.put(scheduleConfig.getIdx(),scheduledFuture);
}
}
CmsSchedulerService에 ApplicationEventPublisher 를 의존성을 주입해줍니다. 그리고 scheduelTask 메소드에서 eventPublisher.publicEvent를 통해 이벤트 리스너를 적용해 줍니다.
publicEvent 적용을 통해 스케줄링 시작, 스케줄링 완료 , 스케줄링 실패에 대한 로그를 비동기 처리를 해줍니다.
로그 결과
위 테이블 결과와 같이 로그 정보가 남는것이 확인이 됩니다.
만약 Quartz 를 이용했다면 JobListener를 이용하여 로그 관리가 가능하지만 Spring 스케줄러는 그렇지 못한것이 단점이었습니다. 하지만 위와 같이 Quartz의 JobListener와 비슷한 느낌을 줄 수 있는 이벤트 리스너를 통해 로그관리를 할 수 있게 되었습니다.
'프로그램 언어 > Spring' 카테고리의 다른 글
Spring Batch 개념을 이해하고 적용해보기 (4) | 2024.10.27 |
---|---|
Spring 스케줄러 (ThreadPoolTaskScheduler)를 이용한 동적 스케줄 관리 적용기 (1) (4) | 2024.10.16 |
Spring Cloud OpenFeign 정리 (1) | 2024.10.16 |
Hazelcast Multicast / Tcp-ip 적용하기 (0) | 2024.02.29 |
hazelcast-client 적용하기(실전편2) (0) | 2024.02.27 |
- Total
- Today
- Yesterday
- 리눅스
- Cache
- leatcode
- 개념 이해하기
- 알고리즘
- dfs
- dockerfile
- 컨테이너
- mybatis
- Linux
- hazelcast
- 스케줄러
- 이미지
- 권한
- 정의
- MySQL
- Quartz
- 도커
- Java
- insert
- 캘린더
- ncp
- centos7
- 네이버 클라우드
- docker
- 캐시
- 격리수준
- Lock
- LocalDate
- spring
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |