[WebSocket & MessageQueue] 카카오톡 시스템 디자인
[카카오톡 시스템 디자인 | WebSocket | 메시지 큐 | SQL vs NoSQL](https://www.youtube.com/watch?v=VODXNECZOBQ) |
Chat Server / API Server 나누기
- WebSocket은 Open Connection을 유지해줘야 되기 때문에 따로 Chat Server 를 만들어서 관리
- 일반적인 리퀘스트 (로그인 / 프로필 사진 바꾸기) 는 API Server 에서 HTTP 로 관리
메시지 큐 (Message Queue)
- ex) Kafka, RabbitMQ
- 서비스들 간에 데이터를 주고 받는 방법 중에 하나
- 메시지 큐를 사용하지 않고 서비스간 데이터 통신 방법
- RestAPI / RPC 를 사용하면 Synchronous(동기식) 하게 데이터를 주고 받음
- 메시지 큐를 사용하면 Asynchronous(비동기식) 하게 데이터 처리
- 두 가지 entity를 가짐
- publisher: 이벤트가 일어났을 때 이벤트를 메시지 큐에 넣는 사람
- subscriber: 이벤트가 일어나면 나한테 알려줘라고 메시지 큐한테 subscribe 하고 있는 서비스
장점
- Decoupling
- Service A가 Service B, C, D 모두에 Dependency가 생김
-
ex) Service A - Chat Server 유저가 메시지를 보낼 때(event) 데이터 베이스 저장(Service B), 메시지를 받는 유저한테 메시지 포워드 (Service C), 받는 유저가 지금 로그인해 있지 않는다면 푸시 노티피케이션 (Service D)
- synchronous 하게 하다보면 모든 디펜던시에 관련된 코드를 Service A에 넣어야 함
- ⇒ Service A 는 점점 복잡, 테스트 어려워짐, 디펜더시가 많아짐(커플링이 많다)
- ⇒ 시스템 디자인시 비효율적
- 메시지 큐 적용시 디펜던시가 훨씬 적어짐
- 각각의 서비스는 Message Queue만 알면 됨
- Service A는 Service B, C, D가 존재한다는 사실을 몰라도 됨
- 각각의 서비스는 Message Queue만 알면 됨
1 : 1 채팅 시스템 디자인
웹 서비스의 경우 로그인되어 있거나 로그아웃 되어있거나 똑같이 push notification을 해줘야 하는 것 같다. 왜냐하면, 웹 서비스에서 로그아웃한다고 push notification을 보내도 알 수 있는 것이 아니고 로그인되어 있어도 알림은 필요할 것 같다.
- 로그인 되어 있는 유저들은 각각 챗 서버들 하고 WebSocket 으로 오픈 커넥션이 있음.
- 유저 A가 메시지를 써서 WebSocket을 통해 Chat Server 1로 전송
- 유저 B의 Queue에 메시지를 넣어준다.
- 유저 B의 Queue를 subscribe 하고 있었던 서비스들(Message DB, Chat Server 3)한테 연락이 감
- Message DB는 모든 큐에 subscribe
- DB에다 message를 저장, Chat Server 3이 메시지를 가져와서 유저 B한테 메시지 포워드
데이터 베이스 종류 선택 (SQL vs NoSQL)
- 트래픽 특성
- 엄청난 양의 트래픽 그룹 채팅 - 하루에 600억 메시지
- 오래된 채팅 잘 안봄
- Read / Write ratio 1 : 1 → 둘 다 효율적으로 되야함
- 다른 데이터들과 join 할 필요가 거의 없음
- Relational Database 같은 경우 데이터가 많아지고 index가 많아지면 느려짐
- Key Value Store
- 스케일 하기가 편함
- Read Latency 가 낮음
- Facebook 같은 경우 HBase; 디스코드는 Cassandra를 사용함
- Key 를 만들때 Range Scan 하기 쉽게 디자인 해야함
- 최근에 보낸 메시지일 수록 Key 값이 높게
- 메시지 아이디가 계속 올라가는 방식
그룹 챗 기능 추가
- 그룹 챗 몇명까지 지원 할 거냐에 따라 디자인이 달라질 수 있음
- 그룹 챗 최대 200명까지 지원한다고 가정을 한다면
- 어느정도의 Fan out은 괜찮음
- 유저 A가 챗 서버에 메시지를 보낸다.
- 챗 서버가 그룹에 어떤 멤버들이 있는지 그룹 챗 DB에 물어본다.
- Group Chat DB : Relational DB
- 그룹에 누가 있는지 응답을 받았다면 받아야할 유저들의 Queue에 chat Server가 메시지를 넣어준다.
- 이 후 동일