ApplicationEventPublisher와 스프링 @Async 기능을 사용해서 비동기 이벤트 기반으로 알림 처리.
- 주요 로직 응답 시간에 영향을 주지 않기.
- 코드를 최대한 주요 로직에 집중하고 알림 처리 로직은 분리.
스프링 이벤트 프로그래밍 모델
ApplicationEventPublisher.publishEvent(Event) // 이벤트 발생
@EventListener // 이벤트 처리
public void handlerEvent(Event event)
스프링 @Async 기능 설정
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
// Executor 설정
}
ThreadPoolTaskExecutor
- https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.html
- CorePoolSize, MaxPoolSize, QueueCapacity
- 처리할 태스크(이벤트)가 생겼을 때,
- '현재 일하고 있는 쓰레드 개수'(active thread)가 '코어 개수'(core pool size)보다 작으면 남아있는 쓰레드를 사용한다.
- '현재 일하고 있는 쓰레드 개수'가 코어 개수만큼 차있으면 '큐 용량'(queue capacity)이 찰때까지 큐에 쌓아 둔다.
- 큐 용량이 다 차면, 코어 개수를 넘어서 '맥스 개수'(max pool size)에 다르기 전까지 새로운 쓰레드를 만들어 처리한다.
- 맥스 개수를 넘기면 태스크를 처리하지 못한다.
비동기 이벤트 로직을 구현하기 전에 비동기 관련 설정 생성
package me.weekbelt.studyolle.infra.config;
@Slf4j
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
int processorsNum = Runtime.getRuntime().availableProcessors();
log.info("processor count {}", processorsNum);
executor.setCorePoolSize(processorsNum);
executor.setMaxPoolSize(processorsNum * 2);
executor.setQueueCapacity(50);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("AsyncExecutor-");
executor.initialize();
return executor;
}
}
새로운 스터디를 개설할때 알림이벤트를 발생시키기 위해 ApplicationEventPulisher클래스를 추가해 이벤트를 등록
package me.weekbelt.studyolle.modules.study;
@RequiredArgsConstructor
@Transactional
@Service
public class StudyService {
// ..........
private final ApplicationEventPublisher eventPublisher;
public Study createNewStudy(Study study, Account account) {
Study newStudy = studyRepository.save(study);
newStudy.addManager(account);
eventPublisher.publishEvent(new StudyCreatedEvent(newStudy)); // 이벤트 처리 알림 추가
return newStudy;
}
// .........
}
package me.weekbelt.studyolle.modules.study.event;
@Getter
public class StudyCreatedEvent {
private Study study;
public StudyCreatedEvent(Study study) {
this.study = study;
}
}
해당 이벤트를 처리하는 이벤트 리스너 추가
package me.weekbelt.studyolle.modules.study.event;
@Slf4j
@Async
@Transactional
@Component
public class StudyEventListener {
@EventListener
public void handleStudyCreatedEvent(StudyCreatedEvent studyCreatedEvent) {
Study study = studyCreatedEvent.getStudy();
log.info(study.getTitle() + "is created.");
// TODO 이메일 보내거나, DB에 Notification 정보를 저장하면 됩니다.
}
}
참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#
'스프링과 JPA 기반 웹 어플리케이션 개발 > 7부 알림' 카테고리의 다른 글
76. 관심있는 스터디 변경 알림 (0) | 2020.05.12 |
---|---|
75. 알림 목록 조회 및 삭게 (0) | 2020.05.12 |
74. 스터디 알림 아이콘 변경 (0) | 2020.05.12 |
73. 스터디 개설 알림 (0) | 2020.05.11 |
71. 알림 도메인 (0) | 2020.05.10 |