Be-Developer

[대규모 시스템 설계 기초] 12 채팅 시스템 설계

채팅 시스템 설계

문제 이해 및 설계 범위 확정

요구사항

  • 응답 지연이 낮은 1:1 채팅 / 최대 100명 그룹 채팅 모두 지원
  • WEB / APP 모두 지원, 다양한 단말 지원 (하나의 계정으로 여러 단말 동시 접속 지원)
  • DAU(Daily Active User) 5천만명
  • 사용자 접속상태 표시,텍스트 메세지만 주고받는다.
  • 메세지 길이 제한 10만자
  • 종단간 암호화 필요없음.
  • 채팅 이력 영원히 보관

    개략적 설계안 제시 및 동의 구하기

    서버의 역할

  • Client로 부터 메세지 수신
  • 메시지 전달 및 저장
  • 네트워크 통신 프로토콜은 면접관과 상의하자.
    • HTTP통신이라면 keep-alive 헤더를 사용하면 효율적.

      메시지 수신

      HTTP는 client가 서버에게 연결을 만드는데, 수신에는 서버에서 Client로 임의의 시점에 연결을 만드는 방법이 필요하다.

      polling

      : 클라이언트가 주기적으로 서버에 물어봄. 불필요한 서버자원이 낭비될 가능성이 높다.

      long-polling

      : 클라이언트는 새 메시지가 반환되거나 타임아웃 될때까지 연결을 유지한다.

  • 메시지를 받은 서버와 보낼 서버가 다를 수 있다. -> db 조회가 아닌 바로 발송?
  • 메시지를 많이 받지 않는 클라이언트도 타임아웃때마다 서버자원이 낭비된다.

    WebSocket

  • 서버가 클라이언트에게 비동기 메시지를 보낼때 가장 널리 사용하는 기술이다.
  • 연결의 시작은 클라이언트가,
  • HTTP 프로토콜(40,443) 을 사용하기때문에 방화병에도 잘 동작.
  • 웹소켓을 사용하면 메시지 발신수신시 동일 프로토콜 사용할 수 있다.
  • 클라이언트와 연결을 유지하고있어야하기때문에 서버에서 연결관리를 효율적으로 해야한다.

    개략적 설계안

    stateless service

  • 회원가입, 로그인 등 전형적인 요청/응답 서비스
  • service discovery 서비스, 클라이언트가 접속할 채팅 서버의 DNS 호스트 명을 클라이언트에게 알려주는 역할.

    stateful service

  • 클라이언트와 연결을 유지하고있어야함.

    제3자 서비스 연동

  • 푸시알림 > 알림설계 참고

    규모 확장성

  • 서버 한대로 얼마나 많은 접속을 동시허용할 수 있는가.
  • 접속당 메모리가 10KB 소요된다고 가정 > 1.000명 = 10GB 메모리 필요.

    저장소

    1. 안정성을 보장하는 RDB
    • 프로필, 설정, 친구목록 등.
      1. 채팅 이력을 위한 key-value 저장소
    • 읽기:쓰기 비율 = 1:1
    • 최근 메시지를 가장 많이 조회
    • 검색 혹은 특정 메시지로 점프기능
    • 데이터 접근시간이 가장 낮다.
    • RDB는 인덱스가 커지면 데이터 무작위 접근 처리비용이 크다.
    • HBase , Cassandra

      데이터 모델

  • 1:1 채팅 메세지 테이블
    • PK : message_id (시간순 정렬이 가능해야함)
  • 그룹채팅 메세지 테이블
    • PK : channel_id, message_id
    • channel_id는 partition_key로도 사용가능.

      상세 설계

      Service descovery

      : 클라이언트에게 적합한 채팅 서버(stateful) 추천.

  • 클라이언트의 지정학적 위치, 서버의 용량 등
  • zookeeper 를 많이 사용함.

    메시지 흐름

    1:1 채팅

    1. 메시지 발송
    2. 채팅서버가 수신하여 메시지 동기화 큐에 발송
    3. 메시지 동기화큐
    • DB저장
    • 상대 사용자의 채팅서버에 전송

      상대 사용자의 채팅서버로의 요청은 어떻게 하는가??

    • 상대 사용자의 채팅서버가 없을경우 푸시알림.

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

  • 각 단말에서 max_message_id 를 가진다. (해당 단말에서 최신메시지 추적 용도)
  • 마지막 메시지 id보다 max값이 더 작으면 동기화.

    소규모 그룹채팅

  • 그룹채팅 구성원 각각 수신큐를 가지고있으며, 메시지 발송시 각 큐로 메시지가 복제된다.
  • 수신자는 자기큐만 보면 되서 동기화 플로우가 단순하다.
  • 그룹이 크지 않으면 메시지를 수신자별로 복사해서 큐에 넣는 작업의 비용이 문제되지 않는다.
  • wechat의 그룹최대 크기는 500명이고, 이방법을 사용.

    큐를 동적으로 생성/삭제 쉽게할수있는 메시지 브로커??

    접속상태 표시

  • 접속상태 서버와 웹소켓 연결을 하며, 키-값 저장소에 last_Active_at을 저장한다.
  • 로그아웃시 offline처리가 필요하다.
  • 클라이언트가 heartBeat를 서버로 보내고, 일정기간동안 heartBeat 미수신시 오프라인으로 한다.
    • 웹소켓이 잠시 끊어지는 (터널통과같은)상황에서 불필요한 업데이트를 줄이기 위함.
  • 상태정보 전송
    • 각 친구관계마다 웹소켓 채널을 두어 라이브로업데이트 > 친구가 많으면 비용,시간이 비효율적
    • 특정 시점(채팅방 입장)에 읽게 함
    • 사용자가 수동 업데이트(버튼) 유도

      마무리

      더 논의할 주제

  • 미디어 지원하는 채팅
    • 압축
    • 클라우드 저장소
    • 썸네일
  • 종단간 암호화
  • 캐시
    • 클라이언트에 이미 읽은 최신 메시지를 캐시
  • 로딩 속도 개선
    • slack은 지역적으로 분산하는 네트워크를 구축함. (Flannel)
    • image
    • 앱을 켰을때 가장 가까운 AWS 지역에 웹소켓을 열고, 채널,유저,봇 등 모두 캐싱해두어 유저 검색 등 빠르게 대응할수있게된다.
    • 프로필 변경 과 같은 이벤트를 클라이언트가 view를 바꿀때 subscription 하여 효율을 높였다.
  • 오류처리
    • 채팅 서버 오류 : 클라이언트에게 다른 서버를 배정하고 다시 접속할 수 있도록 해야한다.
    • 메시지 재전송 : 재시도나 큐는 안정적 전송을 보장하기위해 사용되는 기법.

  • [Wechat e2e encrypt]
  • Slack 지역적 분산 네트워크
  • slack engineering 좋네요
  • Line