웹소켓 서버를 구축한 경험이 있다. 당시에는 단일 노드로 충분하다고 생각되었고, 멀티노드 구성 시 신경쓸 것들이 많아서 단일노드로 구성했다.
하지만 그때 멀티노드로 구성하지 못한게 아쉬워서 개인 프로젝트로 웹소켓 서버 멀티노드 구성을 구현해보려 한다.
이 글을 구현 전에 멀티노드 구성에서 고려해야 하는 몇가지 포인트에 대해서 알아본다.
1. 동일한 topic 에 참가한 client 가 서로 다른 서버와 연결되는 경우
Case
- 채팅방에 접속한 사용자 A는 서버1에 연결
- 같은 채팅방의 사용자 B는 서버2에 연결
- 단순 broadcasting 으로는 A가 보낸 메시지가 B에게 전달되지 않음
해결방안
Redis PubSub 을 이용해서 보통 문제를 해결한다.
- 메세지 브로드캐스팅 시 서버내에서 local broadcasting 이후 redis 를 통해 다른 노드에 broadcasting 을 요청한다.
- broadcasting 요청을 받은 각 서버는 local broadcasting 을 수행한다.
2. 배포 시 커넥션이 고르게 분배되지 않는 문제
Case
- 새 버전 배포 시 서버 재시작으로 모든 웹소켓 연결이 끊김
- 클라이언트는 연결이 끊긴 직후 자동 재연결 시도
- 이 때 남은 서버에 연결이 증가함
- 특히 롤링배포의 경우 1 up, 1 down 시 가장 마지막까지 남아있는 old version 서버와 배포 이후 가장 처음 올라온 new version 서버에 연결이 집중된다.
해결방안
- Load Balancing 을 가장 커넥션이 적은 서버를 우선해서 하는것
- 이 방법은 새로운 노드가 추가되었을 때 connection 이 0개로 시작하고 이후 맺어지는 커넥션을 전부 신규 노드가 받도록 할 수 있다.
- 기존 노드에 부하가 감지되었기 때문에 노드를 추가하는데 기존 커넥션을 신규노드가 가져가지는 못하므로 부하가 있던 노드는 상태가 변하지 않는다.
- 분산 websocket 환경에서는 custom 하게 Load Balancing 을 하는 로직이 필요하다. 아래는 몇가지 예시이다.
- 배포 시 기존 서버의 커넥션을 재분배 하는 방법
- 특정 시간동안 metric 이 기준치 이상인 노드들만 커넥션을 재분배 하는 방법
- 특정 시간 주기로 전체 웹소켓 연결을 전부 reset 해서 노드간 Load 를 균형있게 유지하는 방법