message: MessageBroker middleware
Closed this issue · 0 comments
platanus-kr commented
스케일아웃을 위한 어플리케이션간 메시지 전달 미들웨어 도입
시작 전 생각 했던 것
1) 예상
message
모듈을 스케일아웃 하면 어플리케이션끼리 메시지를 전달받는 구조가 필요함. 종착지는 달라도 채팅방에 포함된 사람은 모두 같은 메시지를 수신 할 수 있어야 하니까.- 웹소켓은 stateful하니 처리를 분산하기 위해 로드밸런싱을 하지만 한번 연결되면 그 어플리케이션과 접속을 유지하니 로드밸런서의 의미가 없을것 같다는 생각,
web
모듈과message
모듈이 쌍이 아니라 각자의 로드밸런서 풀을 가져야 할 것 같다는 생각. - 카프카를 어느 시점에서 메시지를 produce하고 consume 해야 하는가? 모델링은?
2) 예상과 달랐던 점
- Spring Kafka는 내가 기대했던것보다 많은 편의를 제공한다. 토픽 구독처리, 구독 종료처리 등을 자동으로 진행한다. 그래서 offset 커밋에 신경쓰지 않아도 됨.
- 메시지 브로커가 채팅 메시지 전달을 책임지더라도, 그것은 어플리케이션간 전달의 역할일 뿐이지 어플리케이션에서 사용자까지 전달하는 비즈니스 구현은 어플리케이션이 담당해야 한다. 그래서 여전히 채팅방과 웹소켓 세션을 쌍으로 갖는 pub-sub 구현은 유지되어야 한다. 프로젝트 초기부터 염두하고 있던 내용.
3) 정말로 필요했던 것
- Kafka, 메시지 브로커에 대한 이해
- 미들웨어 클러스터 구축
- 무거운 Kafka 모드와 메시지 브로커를 필요로 하지 않는 가벼운 단독 모드의 공존
- Spring Boot의 프로파일 기능
- 서비스 매쉬
이 티켓에서 실제로 한 것
메시지 브로커 구축
카프카 기본 구조 파악
- 토픽, 파티션, 그룹, 오프셋 전략의 이해
- PAC의 설계 → 하나의 토픽으로 하나의 파티션에 최신 메시지만 전달.
Zookeeper 클러스터, KRaft 클러스터
- 로컬용 테스트로는 zookeeper 사용 결정
- 로컬에서 쓸때는 단독노드로 쓰고 싶었는데..
모니터링을 위한 툴
- kafka-ui 도입
- 모니터링 툴이 클러스터 모드가 아니면 안받아줌..
메시지 처리 사이클에 메시지 브로커 추가
KafkaConfig 추가
- 메시지 전달을 위한
BrokerChatMessage
DTO 객체와 Serializer/Deserializer 지정 (json) - Producer(send), Comsumer(listener) 구현
WebSocketHandler 구현체 분리
- 어플리케이션 자체 메시지 처리의 경우
- 채팅방 구독과 메시지 발송이 도메인 안에서 이뤄짐
- 메시지 전달 미들웨어의 경우
web
모듈로 부터 메시지 전송 요청이 오면 스케일아웃된 어플리케이션이 메시지를 전달받을 수 있도록 메시지 브로커KafkaChatPublishAdaptor.sendMessage()
로 전송처리 해야함. 핸들러는 여기서 역할이 종료됨.- 메시지 수신은 카프카 리스너
KafkaChatConsumerAdaoptor.consume()
가 받고 직접MessageBroadcaster
로 같은 채팅방 내 모든 구독자에게 메시지 송신을 요청함.
- 전략패턴으로 변경 할 수 있을것 같은데 한번 고려해볼 것.
스프링 프로파일
큰 비용 필요 없는 단독모드의 유지
- 여전히 pub-sub 구현이 존재해야 한다면 굳이 메시지 브로커에 의존하지 않는 구현체를 제거할 필요가 없음.
- 스프링 프로파일 기능으로 WebSocketHandler의 구현체만 바꿔서 로딩
- Bean 이름 지정 → standalone, kafka
- 테스트를 어떻게 해야할지 난감.. 좀 생각해보기.
이후 구현할 내용
- QueryDSL
- ExceptionHandler
- Dockerfile
- view 템플릿 개선
→ 이것들 목매지 말고 우선 테스트 가능한 코드로 리팩토링 하는게 먼저일 것 같음