동시 접속 20만 이 이 설계의 첫 제약입니다. 연결은 상시 점유입니다. 아무 메시지가 오가지 않아도 메모리와 소켓을 계속 씁니다. 메시지 처리는 순간 부하라 성격이 다릅니다.
자원 성격이 다르면 따로 늘려야 합니다. 그래서 연결을 받는 계층을 떼어냅니다.
왜 한 서버에 두면 안 되나
한 서버가 연결과 처리를 함께 맡으면 둘 중 하나가 낭비됩니다.
| 상황 | 결과 |
|---|---|
| 접속자는 많고 대화는 조용하다 | 연결 때문에 서버를 늘렸는데 CPU 가 남는다 |
| 접속자는 적고 대화가 활발하다 | CPU 때문에 늘렸는데 연결 수용량이 남는다 |
배포도 문제가 됩니다. 채팅 로직을 고칠 때마다 서버를 재시작하면 20만 개의 연결이 한꺼번에 끊깁니다. 클라이언트가 동시에 재접속을 시도해 그 자체가 부하가 됩니다.
계층을 나누면 처리 계층만 배포할 수 있고 연결은 유지됩니다.
게이트웨이가 알아야 하는 것
게이트웨이는 채팅 로직을 모릅니다. 어느 사용자가 어느 게이트웨이에 붙어 있는지만 알면 됩니다. 처리 계층이 "이 사용자에게 보내라" 고 하면 해당 게이트웨이로 넘깁니다.
이 접속 위치 정보를 어디에 두느냐가 다음 판단입니다.
| 방식 | 특징 |
|---|---|
| 공유 저장소에 기록 | 어느 처리 노드에서든 조회한다. 조회가 매 전달마다 붙는다 |
| 게이트웨이 전체에 뿌린다 | 조회가 없다. 게이트웨이 수가 많으면 낭비가 크다 |
접속과 종료가 잦으므로 이 정보는 자주 바뀌고 짧게 살아 있습니다. 영구 저장소보다 만료가 있는 캐시가 맞습니다.
연결이 끊기는 것은 정상이다
모바일에서 연결은 수시로 끊깁니다. 그래서 게이트웨이는 끊김을 오류로 다루지 않습니다. 접속 위치를 지우고, 그 사용자에게 갈 메시지는 채널에 남겨 둡니다. 다시 붙으면 못 받은 것부터 가져갑니다.
여기서 접속 상태를 "끊김 즉시 오프라인" 으로 바꾸면 화면이 깜빡입니다. 짧은 유예를 두고 그 안에 다시 붙으면 상태를 유지합니다.