1단계 문제 이해 및 설계 범위 확정
- 응답지연이 낮은 일대일 채팅 기능
- 최대 100명까지 참여할 수 있는 그룹 채팅 기능
- 사용자의 접속상태 표시 기능
- 다양한 단말 지원
- 푸시 알림
2단계 개략적 설계안 제시 및 동의 구하기
채팅 서비스
- 클라이언트들로부터 메시지 수신
- 메시지 수신자 결정 및 전달
- 수신자가 접속 상태가 아닌 경우에는 접속할 때까지 해당 메시지 보관
HTTP 프로토콜을 이용해 서버가 연결을 만드는 것처럼 동작하는 기법 3가지
- 폴링
클라이언트가 주기적으로 서버에게 새 메시지가 있냐고 물어보는 방법
- 롱폴링
클라이언트는 새 메시지가 반환되거나 타임아웃 될 때까지 연결을 유지, 메시지를 반환받으면 연결을 종료하고 새로운 요청을 보낸다.
단점
- 로드밸런싱을 사용하는 경우, 메시지를 받은 서버는 해당 메시지를 수신할 클라이언트와의 롱 폴링 연결을 가지고 있지 않은 서버일 수 있다.
- 서버 입장에서는 클라이언트가 연결을 해제했는지 아닌지 알 좋은 방법이 없다.
- 여전히 비효율적. 메시지를 많이 받지 않는 클라이언트도 타임아웃이 일어날 때마다 주기적으로 서버에 다시 접속할 것
- 웹소켓
서버가 클라이언트에게 비동기 메시지를 보낼 때 가장 널리 사용하는 기술이다. 웹소켓 연결은 클라이언트가 시작하고 한번 맺어진 연결은 양방향이다. 처음에는 HTTP 연결이지만 특정 핸드셰이크 절차를 거쳐 웹소켓 연결로 업그레이드 된다. 웹소켓은 80, 443 포트를 그대로 쓰기 때문에 방화벽이 있는 환경에서도 잘 동작한다.
개략적 설계안
채팅 시스템 크게 3부분
- 무상태 서비스 → 로그인, 회원가입, 사용자 프로파일 표시
- 상태유지 서비스 → 채팅 서비스
- 제3자 서비스 연동 → 알림 서비스
3단계 상세 설계
서비스 탐색
클라이언트의 위치, 서버의 용량 등을 기준으로 클라이언트에게 가장 적합한 채팅 서버를 추천. 서비스 탐색 기능으로 널리 쓰이는 오픈 소스 솔루션은 아파치 주키퍼가 있다.
메시지 흐름
1:1 채팅 메시지 처리 흐름
- 사용자 A가 채팅 서버 1로 메시지 전송
- ID 생성기를 사용해 ID 결정
- 메시지 동기화 큐로 전송
- 메시지 키-값 저장소에 보관
- 사용자 B가 접속 중이라면 B가 접속 중인 채팅 서버로 전송, 아니라면 푸시 알림 서버로 보냄
- 채팅 서버 2는 메시지를 사용자 B에게 전송
여러 단말 사이의 메시지 동기화
각 단말은 cur_max_message_id라는 변수를 유지하는데, 해당 단말에서 관측된 가장 최신 메시지의 ID를 추적한다.
새 메시지 기준
- 수신자 ID가 현재 로그인한 사용자 ID와 같다.
- 키-값 저장소에 보관된 메시지로서, 그 ID가 cur_max_message_id보다 크다.
소규모 그룹 채팅에서의 메시지 흐름
사용자마다 메시지 동기화 큐를 만들어 사용하는 방법
- 새로운 메시지가 왔는지 확인하려면 자기 큐만 보면 되니까 메시지 동기화 플로가 단순하다.
- 그룹이 크지 않으면 작업 비용도 비싸지 않다.
접속상태 표시
접속상태 서버는 클라이언트와 웹소켓으로 통신하는 실시간 서비스의 일부이다.
사용자 로그인
웹소켓 연결이 맺어지고 나면 접속상태 서버는 A의 상태와 last_active_at 값을 저장소에 보관한다.
로그아웃
키-값 저장소에 보관된 상태가 offline으로 바뀌게 된다.
접속 장애
클라이언트로 하여금 박동 이벤트를 접속상태 서버로 보내도록 하고 마지막 이벤트를 받은 지 x초 이내에 또 다른 박동 이벤트 메시지를 받으면 사용자 상태를 온라인으로 유지한다.
대규모 인원일 때, 상태 갱신 성능 문제
사용자가 그룹 채팅에 입장하는 순간에만 상태 정보를 읽어가게 하거나, 수동으로 접속상태를 갱신하도록 유도
'정기간행물 > daily' 카테고리의 다른 글
구글 드라이브 설계 (대시설기) (0) | 2023.10.09 |
---|---|
유튜브 설계 (대시설기) (0) | 2023.10.08 |
검색어 자동완성 시스템 (대시설기) (1) | 2023.10.04 |
뉴스 피드 시스템 설계 (대시설기) (0) | 2023.10.02 |
알림 시스템 설계 (0) | 2023.09.29 |