Spring Integration을 사용하던중 메세지 기반 처리를 하기위해 비동기 처리를 해야했습니다.
기존에 사용하던 Direct Channel을 사용했을때 비동기 처리가 되지않아던 것을 해결하는 과정을 정리한 글입니다.
Direct Channel
point-to-point 채널이지만 PublishSubscribeChannel입니다.
구독자에게직접 메시지를 발송하지만, point-to-point채널이기에 하나의 endPoint에 message를 전송한다는 점에서
PublishSubscribeChannel과 다릅니다.
특히 중요한 점은 단일 스레드로 구현이 됩니다.
문제 원인
Direct Channel을 단일 스레드입니다.
그래서 해결한 방법은 gateway로 넘겨줄때 ThreadPool을 직접 설정하여 스레드를 사용하였습니다.
과정을 보면 아래와 같습니다.

하지만 고민이 생겼습니다.
Command를 넘겨줄때 즉, Controller에서 비동기 처리를 해야만 했나? 라는 것입니다.
핵심 코드를 보면 Controller에서 gateWay에 요청을보내고 있습니다.
executor.execute(() ->
commendGateway.request(postCreate, loginUser.getUser().getUserId()));
return ResponseEntity.ok(ResponseDto.success());
비동기 처리를 하는 이유를 다시한번 생각해 보았습니다.
비동기 처리를 하는 이유
제가 비동기 처리를 사용했던 이유중 하나는 처리 시간을 줄이기 위한것이 큽니다.
즉, Get을 제외한 DB에 접근해서 어떠한 요청을 비동기로 빠르게 처리하기 위함입니다.
다시 문제 원인으로 돌아와서 비동기가 시작되는 지점이
Controller가 좋을지
Router 혹은 EndPoint가 좋을지 고민해 보았습니다.
그리고 Controller 보다는 Router에서 EndPoint로 진입할때 비동기 처리를 하는것이
더 자연스럽다고 판단하였습니다.
EndPoint에서 실질적인 작업이 이루어지기 때문입니다.
그럼 아래와 같은 Flow로 변경이 됩니다.

변경 된 후 코드
commendGateway.request(postCreate, loginUser.getUser().getUserId());
스레드 풀을 사용하지 않고 있습니다.
MessageChannel을 ExecutorChannel로 변경하였기 때문입니다.
ExecutorChannel 변경이유

unlike DirectChannel, the ExecutorChannel does not support a shared transactional context between sender and handler, because the Executor typically does not block the sender's Thread since it uses another Thread for the dispatch. (SyncTaskExecutor is an exception but would provide no value for this channel. If synchronous dispatching is required, a DirectChannel should be used instead).
ExecutorChannel의 설명입니다.
마지막 문장이 핵심입니다.
If synchronous dispatching is required, a DirectChannel should be used instead).
공식 문서에도 나와있어 ExecutorChannel을 사용하였습니다.
코드 변경 후 스레드가 정상적으로 비동기 처리되는것을 확인하였습니다.

느낀점
Spring Integration은 인터넷에 정보가 많이 없습니다.
기껏해봐야 스프링 인 액션의 예제이거나 Spring Integration에 대한 정보정도 입니다.
그래서 공식 문서의 중요성을 뼈속깊이 알게 되었고 Spring Integration의 채널에 대해 더 잘알게 되었습니다.
참고
'Project > 개인프로젝트' 카테고리의 다른 글
[Error] Multi Module 적용 에러 (0) | 2023.10.19 |
---|---|
Spring Integration 적용하기 (0) | 2023.10.07 |
ThreadLocal적용하여 Thread 안에서의 값을 공유하기 (0) | 2023.10.07 |
TransactionSynchronizationManager를 사용해 Transaction 이후에 Event 등록하기 (0) | 2023.10.06 |
ThreadLocal 초기화 에러 (0) | 2023.10.02 |
Spring Integration을 사용하던중 메세지 기반 처리를 하기위해 비동기 처리를 해야했습니다.
기존에 사용하던 Direct Channel을 사용했을때 비동기 처리가 되지않아던 것을 해결하는 과정을 정리한 글입니다.
Direct Channel
point-to-point 채널이지만 PublishSubscribeChannel입니다.
구독자에게직접 메시지를 발송하지만, point-to-point채널이기에 하나의 endPoint에 message를 전송한다는 점에서
PublishSubscribeChannel과 다릅니다.
특히 중요한 점은 단일 스레드로 구현이 됩니다.
문제 원인
Direct Channel을 단일 스레드입니다.
그래서 해결한 방법은 gateway로 넘겨줄때 ThreadPool을 직접 설정하여 스레드를 사용하였습니다.
과정을 보면 아래와 같습니다.

하지만 고민이 생겼습니다.
Command를 넘겨줄때 즉, Controller에서 비동기 처리를 해야만 했나? 라는 것입니다.
핵심 코드를 보면 Controller에서 gateWay에 요청을보내고 있습니다.
executor.execute(() ->
commendGateway.request(postCreate, loginUser.getUser().getUserId()));
return ResponseEntity.ok(ResponseDto.success());
비동기 처리를 하는 이유를 다시한번 생각해 보았습니다.
비동기 처리를 하는 이유
제가 비동기 처리를 사용했던 이유중 하나는 처리 시간을 줄이기 위한것이 큽니다.
즉, Get을 제외한 DB에 접근해서 어떠한 요청을 비동기로 빠르게 처리하기 위함입니다.
다시 문제 원인으로 돌아와서 비동기가 시작되는 지점이
Controller가 좋을지
Router 혹은 EndPoint가 좋을지 고민해 보았습니다.
그리고 Controller 보다는 Router에서 EndPoint로 진입할때 비동기 처리를 하는것이
더 자연스럽다고 판단하였습니다.
EndPoint에서 실질적인 작업이 이루어지기 때문입니다.
그럼 아래와 같은 Flow로 변경이 됩니다.

변경 된 후 코드
commendGateway.request(postCreate, loginUser.getUser().getUserId());
스레드 풀을 사용하지 않고 있습니다.
MessageChannel을 ExecutorChannel로 변경하였기 때문입니다.
ExecutorChannel 변경이유

unlike DirectChannel, the ExecutorChannel does not support a shared transactional context between sender and handler, because the Executor typically does not block the sender's Thread since it uses another Thread for the dispatch. (SyncTaskExecutor is an exception but would provide no value for this channel. If synchronous dispatching is required, a DirectChannel should be used instead).
ExecutorChannel의 설명입니다.
마지막 문장이 핵심입니다.
If synchronous dispatching is required, a DirectChannel should be used instead).
공식 문서에도 나와있어 ExecutorChannel을 사용하였습니다.
코드 변경 후 스레드가 정상적으로 비동기 처리되는것을 확인하였습니다.

느낀점
Spring Integration은 인터넷에 정보가 많이 없습니다.
기껏해봐야 스프링 인 액션의 예제이거나 Spring Integration에 대한 정보정도 입니다.
그래서 공식 문서의 중요성을 뼈속깊이 알게 되었고 Spring Integration의 채널에 대해 더 잘알게 되었습니다.
참고
'Project > 개인프로젝트' 카테고리의 다른 글
[Error] Multi Module 적용 에러 (0) | 2023.10.19 |
---|---|
Spring Integration 적용하기 (0) | 2023.10.07 |
ThreadLocal적용하여 Thread 안에서의 값을 공유하기 (0) | 2023.10.07 |
TransactionSynchronizationManager를 사용해 Transaction 이후에 Event 등록하기 (0) | 2023.10.06 |
ThreadLocal 초기화 에러 (0) | 2023.10.02 |