Aarchitecture/Domain Driven Design

비동기 이벤트

훈지런 2023. 1. 27. 18:30

이벤트를 이용해 도메인이 뒤섞이는 문제는 해결을 했지만 외부시스템의 성능에 영향을 받는건 해결이 안됬음.

가장 쉽게 생각할수있는 해결방안은 비동기로 처리하는것

카톡알림이나 이메일 알림같은경우 10초 20초 정도 늦게 도착해도 전혀 문제될게 없어보인다.

A를 하면 일정시간안에 B를 해라 같은 경우에 비동기 처리를 하면 해결될것같다.

비동기 이벤트


  • 로컬 핸들러를 비동기로 실행
  • 메시지 큐 사용
  • 이벤트 저장소와 이벤트 포워더 사용
  • 이벤트 저장소와 이벤트 제공 API 사용

1. 로컬 핸들러를 비동기로 실행

@Service
public class OrderCanceledEventHandler{

    // ...

    @Async
    @EventListener(OrderCanceledEvent.class)
    public void handle(OrderCanceledEvent event){
        refundService.refund(event.getOrderNumbr());
    }

}

스프링에서 제공하는 @Async 어노테이션을 이용하면 쉽다.

2. 메시지큐 사용

메시지큐를 사용하는 방식엔 카프카(Kafka)나 래빗MQ(RabbitMQ)가 있음.
일반적으로 이벤트를 발생시키는 주체와 이벤트 핸들러가 별도 프로세스에서 동작한다

3. 이벤트 저장소와 이벤트 포워더 사용

포워더는 별도의 스레드를 이용해서 주기적으로 이벤트 저장소에서 이벤트를 가져와 이벤트 핸들러를 실행

4. 이벤트 저장소와 이벤트 제공 API 사용

 

외부 API의 이벤트핸들러가 API서버를 통해 이벤트 목록을 가지고 감
포워더 방식과 API 방식의 차이점은 이벤트를 전달하는 방식에 있다. 포워더 방식이 포워더를 이용해서 이벤트를 외부에 전달한다면, API 방식은 외부 핸들러가 API 서버를 통해 이벤트 목록을 가져간다

이벤트 적용시 고려사항


  1. 포워더에서 전송실패를 몇번까지 허용해줄것지
  2. 이벤트 손실에 대해서 어떻게 대응할 것인지
  3. 이벤트 처리 순서는 어떻게 할것인지
  4. 이벤트 재처리에대한 문제는 어떻게 할것인지

1. 몇번 허용할지..

같은 앱 서버내에서 다른 애그리거트의 이벤트를 참고하는것은 어렵지 않으나 마이크로 서비스 간 메시징 시스템이나 포워더를 사용해서 이벤트 처리를 하는 경우에는 전송실패나 손실이 발생할수 있다.
따라서, 포워더에서 전송실패를 몇번까지 허용해줄것지정해야 함.
실패했다고해서 무한정 반복실행할순 없는 노릇...

2. 이벤트 손실 대응

이벤트 저장소를 사용하는 방식은 이벤트 발생과 저장을 한 트랜잭션으로 처리하기때문에 안전하지만, 로컬 핸들러를 이용해서 비동기로 처리할때 실패하는 경우 이벤트 유실은 어떻게 할지.

3. 처리 순서 정책

이벤트 발생 순서대로 외부 시스템에 전달해야하는 경우엔 이벤트 저장소를 이용하는것이 가장 적합하지만
메시징 시스템의 경우 이벤트 발생순서와 메시지 전달 순서가 다를수 있기 때문.

4. 이벤트 재처리에 대한 문제

동일한 이벤트를 다시 처리해야할때 이벤트를 어떻게 해야할지 결정해야함.
가장 쉬운방법으로는 마지막 순번을 기억해두었다가 이미 처리된 순번의 이벤트가 도착하면 무시하는 방법이 있음. 그 외에는 이벤트를 멱등으로 처리하는 방법도 있다. 그러니까 같은 이벤트가 여러번 날라와도 항상 처리결과가 동일한 결과를 갖게 하는것.

'Aarchitecture > Domain Driven Design' 카테고리의 다른 글

이벤트  (0) 2023.01.26
Layered Archiecture  (0) 2023.01.25
애그리거트  (0) 2022.12.29
바운디드 컨텍스트  (0) 2022.12.21
도메인 주도 설계란?  (0) 2022.12.20