platanus-kr/plata-anywhere-chat

message: MessageBroker middleware

Closed this issue · 0 comments

스케일아웃을 위한 어플리케이션간 메시지 전달 미들웨어 도입

시작 전 생각 했던 것

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 템플릿 개선

→ 이것들 목매지 말고 우선 테스트 가능한 코드로 리팩토링 하는게 먼저일 것 같음