WebSocket - Multi Node

Tags
Published
Author
웹소켓 서버를 구축한 경험이 있다. 당시에는 단일 노드로 충분하다고 생각되었고, 멀티노드 구성 시 신경쓸 것들이 많아서 단일노드로 구성했다. 하지만 그때 멀티노드로 구성하지 못한게 아쉬워서 개인 프로젝트로 웹소켓 서버 멀티노드 구성을 구현해보려 한다. 이 글을 구현 전에 멀티노드 구성에서 고려해야 하는 몇가지 포인트에 대해서 알아본다.

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 를 균형있게 유지하는 방법