2023-07-31-TIL
Today I Learned
@Async
@Async는 메서드를 호출한 스레드가 아니라 별도 스레드에서 실행되게 하는 Spring 애너테이션이다. 설정 클래스에 @EnableAsync를 붙여야 동작한다. Spring 가이드는 @EnableAsync가 @Async 메서드를 백그라운드 스레드 풀에서 돌리는 기능을 켠다고 설명한다. 동기와 비동기의 차이 자체는 동기·비동기 강의 정리에 따로 적어 두었다.
쓰기 전에 알아 둘 점이 몇 가지 있다. 모두 Spring 레퍼런스의 스케줄링 장에 나온다.
- 반환 타입: 결과가 필요하면
Future나CompletableFuture를 반환해야 한다. 호출한 쪽은 결과가 나중에 채워질 객체를 바로 받는다. - 예외 처리:
Future를 반환하면 메서드 안에서 난 예외가get()을 호출할 때 던져진다.void메서드의 예외는 호출한 쪽으로 전달되지 않고 기본적으로 로그만 남는다. 따로 처리하려면AsyncUncaughtExceptionHandler를 등록한다. - 같은 클래스 안의 호출: 기본 모드는 프록시 방식이라서 프록시를 거치는 호출만 가로챌 수 있다. 같은 클래스 안에서
this.method()로 부르면 비동기로 실행되지 않는다. 가이드도 객체를new로 직접 만들면 비동기로 동작하지 않고 Spring 빈이어야 한다고 강조한다. 실행기:
@Async("otherExecutor")처럼 빈 이름을 넘겨 메서드마다 다른 실행기를 쓸 수 있다. 스레드 풀 크기와 큐 용량을 정하지 않으면 작업이 몰릴 때 어떻게 동작할지 예측하기 어렵다.- https://spring.io/guides/gs/async-method/
- https://www.baeldung.com/spring-async
- https://www.digitalocean.com/community/tutorials/spring-async-annotation
- https://velog.io/@gillog/Spring-Async-Annotation%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0
ShedLock
@Scheduled 작업은 애플리케이션 인스턴스마다 따로 돈다. 서버를 두 대 띄우면 같은 배치가 두 번 실행된다. ShedLock은 이 문제를 막는 라이브러리다. ShedLock README는 목적을 이렇게 요약한다.
“ShedLock makes sure that your scheduled tasks are executed at most once at the same time.”
같은 작업이 동시에 두 번 이상 실행되지 않게 보장한다는 뜻이다. DB, Redis, ZooKeeper 같은 외부 저장소에 잠금 레코드를 두고, 한 노드가 잠금을 잡으면 다른 노드는 기다리지 않고 그 회차를 건너뛴다. 메서드에는 @SchedulerLock을 붙이고 두 값을 정한다.
lockAtMostFor: 잠금을 최대로 유지하는 시간이다. 작업 중인 노드가 죽어도 이 시간이 지나면 잠금이 풀린다. 평소 실행 시간보다 넉넉하게 잡아야 한다.lockAtLeastFor: 잠금을 최소로 유지하는 시간이다. 작업이 아주 빨리 끝나도 서버 간 시계 차이 때문에 다른 노드가 같은 회차를 다시 실행하는 일을 막는다.
README는 ShedLock이 완전한 스케줄러가 아니라는 점도 분명히 한다. 여러 노드에 작업을 나눠 주는 분산 스케줄링이 필요하면 다른 도구를 쓰라고 안내한다.
- https://www.springcloud.io/post/2022-07/shedlock/#gsc.tab=0
- https://yejipro.tistory.com/entry/spring-boot-ShedLock-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95
댓글
아직 댓글이 없습니다