[문제 해결] 분산 서버간 메시지 전송문제 해결하기

neo-the-cow·2024년 5월 25일

문제 해결

목록 보기
2/4
post-thumbnail

실시간 다중 채팅 서비스 프로젝트를 진행하며 겪었던 문제와 해결과정을 기록합니다.

1. 문제 상황과 원인 분석

  • 웹 소켓 서버와 연결된 클라이언트가 메시지를 발송하면 서버 내부의 메시지 브로커 역할을 하는 Sinks에 메시지를 emit() 합니다.
  • Sinks.Many<ChatMessage>를 구독하는 모든 커넥션에 메시지를 전달하고 각 커넥션은 클라이언트로 메시지를 발송합니다.
  • 하지만 웹 소켓 서버가 다중화되고 서로 다른 서버 인스턴스에 연결된 클라이언트 끼리는 메시지를 송/수신 할 수 없습니다.

  • 위처럼 서버-00에 연결된 클라이언트-0x 사이에는 메시지를 정상적으로 송/수신 하지만 서버-01에 연결된 클라이언트-1x에는 메시지가 전달되지 않습니다.
  • 마찬가지로 클라이언트-1x가 발송한 메시지를 클라이언트-0x는 받아볼 수 없습니다.

2. 문제 해결

2.1 해결 방안 1 - MongoDB Tailable Cursor

  • MongoDB에서 지원하는 Tailable Cursor를 사용할 수 있습니다.
  • 컬렉션에 새로운 레코드가 생성되면 Tailable cursor를 통해 구독하고 있는 모든 커넥션으로 메세지가 전달됩니다.

  • 다중화 된 각 서버 노드간 강결합을 피할 수 있고 서버 노드가 추가되거나 제거될 때 네트워크 구성을 변경할 필요가 없어 확장성을 기대할 수 있습니다.
  • 또한 최근 발송된 메시지 레코드를 저장해 메시지 정보의 지속성을 가지게 됩니다.

Capped Collection 문제

  • Tailable cursor는 고정된 크기의 컬렉션에서 지원되기때문에 컬렉션의 레코드 수가 일정 범위를 벗어나게 되면 오래된 메시지 순으로 제거됩니다.
  • 필요에 따라 메시지 영속화 과정이 필요하고 그 과정을 구현하는 오버헤드를 가집니다.

2.2 해결 방안 2 - 이벤트(메시지) 브로커 도입

  • MongoDB는 채팅 이력을 저장하는 저장소로 사용하고 Kafka를 도입해 각 서버 노드가 메시지지를 발행하고 구독하는 방식을 사용할 수 있습니다.

  • 웹 소켓 통신으로 채팅 메시지가 입력되면 Kafka의 채팅 토픽으로 메시지를 발행하고 메시지를 MongoDB에 영속화 합니다.
  • Kafka의 채팅 토픽을 구독하는 서버 노드는 발행된 메시지를 수신하고 처리해 클라이언트에 전달할 수 있습니다.

3. 적용한 방법

  • 이벤트 브로커 Kafka를 도입했습니다.
  • MongoDB는 채팅 이력을 저장하는 저장소의 역할만 수행하게 합니다.
  • 이벤트 브로커 도입으로 채팅 메시지 뿐만 아니라 서버에서 발생하는 다양한 이벤트를 전달하는데 사용하며 확장성을 기대할 수 있습니다.
  • 관련 포스팅: 로컬환경 Kafka 클러스터 구축기
profile
Hi. I'm Neo

0개의 댓글