본문 바로가기
C.W.K.
Stream
Lesson 02 of 07 · published

수평 확장

~12 min · production, scaling, redis

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

상태 없는 HTTP 는 서버만 더하면 되지만 WebSocket 은 달라

HTTP API 는 동일한 서버를 라운드 로빈 부하 분산기 뒤에 더해 확장할 수 있어. 요청 하나가 처리기 안에서 완결되기 때문이야. WebSocket 연결은 오래 유지되므로 서버를 더하면 새 연결 용량은 늘지만 서로 다른 서버의 연결 사이에 메시지를 전달해 주지는 않아. 서버 사이 전체 전송에는 메시지 버스가 필요해.

표준 해법은 Redis Pub/Sub 이야

트랙 4 에서 배운 방식이지. 운영에서는 모든 WebSocket 서버가 나가는 메시지를 Redis 에 발행하고 구독해 받은 뒤 자기 로컬 연결에 펼쳐. 서버를 자유롭게 더하면 Redis 자체가 병목이 될 때까지 용량이 선형으로 늘어나. 아주 큰 규모에서는 Redis Cluster 나 Kafka 를 고려해.

Socket.IO 에는 어댑터가 들어 있어

Socket.IO 를 쓴다면 client_manager=socketio.AsyncRedisManager(...) 한 줄로 확장할 수 있어. 모든 sio.emit() 이 자동으로 서버 사이를 건너가므로 따로 작성할 Pub/Sub 코드는 0줄이야.

Code

구성도·text
  +----------+   +----------+   +----------+
  | Server 1 |   | Server 2 |   | Server 3 |
  | Users A,B|   | Users C,D|   | Users E,F|
  +----+-----+   +----+-----+   +----+-----+
       |              |              |
       +-------+------+-------+------+
               |    Redis Pub/Sub
               |  +-----------+
               +->| redis     |
                  +-----------+

  User A sends "hi" to room R
  Server 1 publishes "ws:room:R" -> Redis
  Redis fans out to all three servers
  Each server broadcasts locally to room R members
  -> A,B,C,D,E,F all receive "hi" within ms
Socket.IO Redis 어댑터·python
import socketio

sio = socketio.AsyncServer(
    async_mode='asgi',
    client_manager=socketio.AsyncRedisManager('redis://redis:6379'),
)

# That's the entire change. sio.emit() now spans all servers.

External links

Exercise

Redis 하나 뒤에 Python Socket.IO 서버 두 대를 띄우고 각각 클라이언트를 열어. 서버 1 의 클라이언트에서 chat:message 를 보내 Redis 어댑터를 거쳐 서버 2 의 클라이언트가 받는지 확인해. Redis 를 멈추면 서버 간 전달도 멈추는지, 다시 시작하면 재개되는지도 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.