책정리/대규모 시스템 설계 기초

채팅 시스템 설계

뽀글보리 2023. 12. 8. 07:45
반응형

12장 채팅 시스템 설계

요구 사항 확인

  • 응답 지연이 낮은 1:1, 그룹 채팅 모두 가능한 앱
  • 모바일 & 웹 모두 지원 ⇒ 하나의 계정으로 여러 단말에 동시 접속 지원
  • 5천만 DAU
  • 100명까지 가능한 그룹 채팅
  • 텍스트만 가능, 사요자 접속상태 표시 지원
  • 10,000자 이하
  • 암호화는 필요 없다.
  • 채팅 이력을 영원히 보관해야한다.

개략적 설계안

메시지 발신 시

  • HTTP 프로토콜을 사용하여 채팅 서비스에 메시지를 보낸다.
  • keep-alive 헤더로 클라이언트와 서버 사이의 연결을 끊지 않고 계속 유지할 수 있다. ⇒ TCP 접속 과정의 핸드세이크 횟수를 줄일 수 있다.

메시지 수신 시

 

HTTP는 클라이언트가 연결을 만들기 때문에, 서버에서 클라이언트로 메시지를 보내는 데이는 쉽게 쓰일 수 없다.

 

폴링

  • 클라이언트가 주기적으로 서버에게 새 메시지가 있느냐고 물어보는 방법
  • 답해줄 메시지가 없는 경우에는 서버 자원이 불필요하게 낭비된다는 문제

롱 폴링

  • 새 메시지가 반환되거나 타임아웃 될 떄까지 연결을 유지한다.
  • 메시지를 보내는 클라이언트와 수신하는 클라이언트가 같은 채팅 서버에 접속하지 않을 수 있다. (로드밸런싱을 라운드 로빈을 사용하는 경우)
  • 서버 입장에서는 클라이언트가 연결을 해제했는 지 아닌지 알 방법이 없다.
  • 비효율적이다. 타임아웃이 일어날 때마다 주기적으로 서버에 다시 접속할 것이다.

웹소켓

  • 가장 널리 사용하는 기술, 메시지 양방향 전송 가능하다.
  • 웹소켓 연결은 클라이언트가 시작, 한번 맺어진 연결은 항구적이며 양방향이다.
  • 처음에는 HTTP 연결이지만 핸드세이크 절차를 거치면 웹소켓 연결로 업그레이드
  • 서버에서 클라이언트에게 비동기적으로 메시지를 전송할 수 있다
  • 방화벽이있는 환경에서도 잘 동작한다, 80/443 같은 기본 포트번호를 그대로 쓰기 때문이다.
  • 영구적으로 웹소켓 연결이 유지되어야하기 때문에 서버 측에서 연결 관리를 효율적으로 해야한다.

개략적 설계안

  • 무상태 서비스
    • 서비스 탐색, 인증 서비스, 그룹 관리, 사용자 프로파일
    • 로드 밸런서 뒤에 위치하며, 로드 밸런스가 요청에 맞는 서비스로 정확하게 전달한다.
  • 상태 유지
    • 채팅 서비스
    • 각 클라이언트가 채팅 서버와 독립적인 네트워크 연결을 유지해야 한다.
  • 제 3자 서비스 연동
    • 푸시 알림

규모 확장성

  • 서버 한 대로 얼마나 많은 접속을 동시에 허용할 수 있느냐?
  • 동시 접속자가 1M이고 접속당 10K의 서버 메모리가 필요하다면, 10GB 메모리만 있다면 모든 연결을 다 처리할 수 있다.
  • 하지만 서버 한대만 쓰겠다고 한다면 면접에서 좋은 점수는 못받겠죠 ,, 또한 SPOF

저장소

  • 사용자 프로파일, 설정, 친구 목록처럼 일반적인 데이터 → 안정성을 보장하는 관계형 데이터베이스에 보관한다. 다중화, 샤딩을 통해 이러너 데이터의 가용성과 규모확정성 보증
  • 채팅 이력
    • 데이터의 양이 엄청나고, 최근 메시지만 주로 들여다본다. 또한 검색하거나 사용자 언급된 메시지만 보거나, 특정 메시지로 점프하거나 이렇게 되는 경우도 있다.
  • 1:1채팅일 경우에는 읽기 : 쓰기 비율이 1:1이다.
  • 키-값 저장소를 추천한다 !
    • 수평적 규모확장이 쉽다.
    • 데이터 접근 지연시간이 낮다.
    • 관계형 데이터베이스의 경우, 인덱스가 커지만 데이터 무작위적 접근을 처리하는 비용이 늘어난다.
    • 페이스북 메신저, 디스코드가 HBase, Cassandra 사용

데이터 모델

 

1:1 채팅을 위한 메시지 테이블

message_id를 기본 키로하고, 메시지 순서를 결정한다.

 

그룹 채팅을 위한 메시지 테이블

 

(channel_id, message_id)의 복합 키를 기본 키로 사용한다. 그리고 channel_id를 파티션 키로도 사용할 것이다.

 

메시지 ID

 

고유하고, 시간 순서대로 정렬 가능하여야 하기 때문에 7장 분산 시스템을 위한 유일 ID 생성기 설계를 참고하여 스노플레이크 생성기를 사용할 수 잇다.

아니면, 지역적 순서 번호 생성기를 이용하는 것이다. 같은 그룹 내에서만 ID 유일성을 보장하면 되기 때문에 전역 ID 생성기에 비해 구현하기 쉬운 접근법이다.

상세 설계

서비스 탐색

 

서비스 탐색이란 클라이언트에게 가장 적합한 채팅 서버를 추천하는 것이다.

위치, 서버 용량을 고려하여 올바른 서버를 추천해야 한다.

아파치 주키퍼와 같은 오픈 소스 솔루션를 사용할 수 있다.

사용자가 로그인을 하면, API를 통해 사용자 인증을 하고, 채팅서버 A와 웹소켓 연결을 맺는다.

 

메시지 흐름

1:1 채팅 메시지 처리 흐름

사용자 A가 B에게 보낸 메시지가 어떤 경로로 처리될까?

사용자가 채팅 서버로 메시지를 전송하면, 메시지 ID 결정하여 메시지를 message queue로 전송한다. 메시지가 키-값 저장소에 보관되면, 사용자B가 서버 접속 중이라면 해당 채팅서버로 전송하고, 접속 중이 아니라면 푸시 알림 서버로 보낸다.

 

여러 단말 사이의 메시지 동기화

 

전화기와 랩톱으로 로그인한 결과, 각 단발은 cur_max_message_id라는 변수로 해당 단말에서 관측한 가장 최신 메시지의 ID를 추적한다. 따라서 메시지가 cur_max_message_id보다 크다면 새 메시지로 간주한다. ⇒ 단말마다 별도로 관리한다.

 

소규모 그룹 채팅에서의 메시지 흐름

 

메시지를 보내면 동기화 큐에 메시지가 복사되고, 이 큐를 사용자 각각에 할당된 메시지 수신함 같은 것으로 생각해도 된다.

  • 새로운 메시지가 왔는 지 자기 큐만 보면 된다.
  • 그룹이 크지 않으면 수신자별로 복사해서 큐에 넣는 작업 비용이 문제되지 않는다.

위챗은 그룹의 크기를 500명으로 제한하여 다음과 같은 접근법 사용

하지만 많은 사용자를 지원해야한다면?

똑같은 메시지를 모든 사용자의 큐에 복사하는 게 바람직하지 않다.

 

접속상태 표시

 

지금 접속 중인가? 를 확인하기 위해서  접속 상태 서버를 통해서 사용자의 상태를 관리한다.

사용자 로그인 : 클라이언트와 실시간 서비스 사이에 웹소켓 연결이 맺어지면 상태와 타임스탬프 값을 키-값 저장소에 보관한다.

로그아웃 : 로그아웃하면 online→offline

접속장애 : 사용자의 인터넷 연결이 끊어지면 웹소켓 지속성 연결도 끊어진다. 그러나 짧은 시간 동안 인터넷 연결이 끊어졌다 복구되는 일은 흔한데, 이때마다 접속 상태를 변경한다면 바람직하지 않다.

따라서, heartbeat event를 접속상태 서버로 보내도록 하고, 마지막 이벤트를 받은 지 x초 이내에 또 다른 박동 이벤트 메시지를 받으면 해당 접속상태를 온란인으로 계속 유지한다.

 

상태 정보의 전송

 

A 접속상태가 변경되었다면, B,C,D가 상태 변화를 구독하도록 한다.

그러나 100000명의 사용자가 있다면, 그룹 채팅에 입장하는 순간에만 상태 정보를 읽어가게 하거나, 접속 상태를 갱신하고 싶으면 수동으로 하도록 유도하는 것이 좋다.

추가적으로 언급할 수 있는 내용

  • 사진이나 미디어를 지원하도록 하는 방법 : 압축 방식, 클라우드 저장소, 섬네일 생성등을 논의
  • 추가적인 보안 조치, 종단 간 암호화 사용을 통해 메시지 발신인과 수신자 이외에는 아무도 메시지 내용을 볼 수 없도록 한다.
  • 이미 읽은 메시지를 캐시해 두면 데이터 양을 줄일 수 있다.
  • 로딩 속도 개선: 슬랙은 사용자의 데이터, 채널 등을 지역적으로 분산하여 앱 로딩 속도를 개선하였다.
  • 오류 처리: 채팅 서버 하나가 죽으면 주키퍼 같은 탐색 기능이 동작하여 클라이언트에게 새로운 서버를 배정하고 다시 접속할 수 있도록 해야한다.
  • 메시지 재전송: 재시도, 큐를 통해서 메시지를 안정적 전송

 

* 가상 면접 사례를 배우는 시스템 설계 12장을 읽고 정리한 내용입니다.

반응형

'책정리 > 대규모 시스템 설계 기초' 카테고리의 다른 글

유튜브 설계  (1) 2023.12.17
검색어 자동완성 시스템 설계  (2) 2023.12.10
뉴스 피드 시스템 설계  (1) 2023.12.06
웹 크롤러 설계  (0) 2023.12.04
URL 단축기 설계  (2) 2023.12.03