상황

스크린샷 2024-10-23 오전 2.19.09.png

채팅 서버의 가용성을 보장하기 위해 기존 단일 서버 방식에서 분산 서버로 변경하여 사용자와 채팅 서버간의 WebSokcet(STOMP) 트래픽을 분산 시키고자 하였습니다.

그러나 WebSocket(STOMP)는 양방향 Stateful 방식여서 클라이언트는 서버와 세션이 연결되어있습니다. 따라서 다른 서버 인스턴스에 세션 연결을한 수신자는 같은 채팅방에 접속하더라도 채팅을 전달 받을 수 없습니다.

스크린샷 2024-10-23 오전 2.28.15.png

문제 해결 방법

따라서 외부 브로커를 사용하여 채팅 서버 인스턴스들이 외부 브로커를 구독하여 모든 서버가 해당 메시지를 받을 수 있도록 처리해야합니다.

해당 기술 선택에 있어 Redis(Pub/Sub)과 Kafka를 고민하였습니다.

https://www.youtube.com/watch?v=73Utd7nDYDs

kafka vs Redis

Kafka Redis
메시지 저장 여부 토픽에 메시지를 일정 주기동안 저장할 수 있음 메시지가 Subscriber 에게 전송되면서 채널에서 바로 삭제됨
메시지 수신 방식 Consumer 가 polling 방식으로 Topic 에서 메시지를 가져감 채널에서 Subscriber 들에게 메시지를 push
전송보장 ack 옵션에 따라 보장 가능 메시지를 수신했는지 따로 확인하지 않음
지연시간 메시지에 대해 ack 옵션에 따라 수신 확인 등의 작업이 있어 redis 보다는 비교적 느림(그래도 빠르다) In-Memory 기반으로 메시지 전송 후 수신 확인같은 별도의 작업이 없어 Kafka 보다 비교적 가볍고 빠름

kafka(안정성)과 Redis(빠른속도) 측면에서 봤을 때, 현재 서비스에서 빠른 전송보다 kafka의 순서보장, 메시지 저장으로 복구 가능성 측면이 더 중요하다고 판단되어 Kafka를 외부 브로커로 사용하기로 결정하였습니다.