← posts/b.log()

blog92@web:~$ cat posts/websocket-13-backpressure-and-flow-control.md

NETWORK1 min read

WebSocket 완전 정복 13편 — 백프레셔와 흐름 제어: bufferedAmount와 slow consumer

느린 클라이언트 몇 개가 서버 메모리를 고갈시키는 slow consumer 문제를 bufferedAmount 임계값으로 방어하는 코드와, 메시지를 버릴지 최신값으로 덮어쓸지 연결을 끊을지 데이터 성격에 따라 정하는 정책, 그리고 반대 방향의 rate limit을 다룹니다.

WebSocket 완전 정복 · 3부. 심화: 확장, 인프라, 운영, 보안 · 16편 중 13편

이전 편: 12편 — 수평 확장

12편에서 서버를 여러 대로 늘려 연결을 나눠 받았습니다. 이번 편은 그 연결 하나하나의 속도 차이를 다룹니다 — 서버가 보내는 속도를 클라이언트가 따라오지 못할 때 무슨 일이 생기고, 무엇을 버리고 무엇을 지킬지를 어떻게 정하는지.

slow consumer — 느린 클라이언트가 서버를 무너뜨린다

서버가 클라이언트 수신 속도보다 빨리 보내면 메모리에 데이터가 쌓입니다. 느린 클라이언트 몇 개가 서버 메모리를 고갈시킬 수 있습니다(slow consumer).

bufferedAmount로 방어하기

ts
const HIGH_WATER = 1 * 1024 * 1024; // 1MB
 
function safeSend(ws: WebSocket, data: string) {
  if (ws.readyState !== WebSocket.OPEN) return;
  if (ws.bufferedAmount > HIGH_WATER) {
    // 정책 선택:
    // (a) 이 메시지 버리기 (실시간 시세처럼 최신값만 의미 있을 때)
    // (b) 최신 상태로 덮어쓰기 (conflation)
    // (c) 연결 끊기 (계속 못 따라오는 클라이언트)
    ws.close(1013, "slow consumer"); // 1013: Try Again Later
    return;
  }
  ws.send(data);
}

데이터 성격에 맞는 정책

  • 최신값만 중요한 데이터(시세, 센서, 게이지): conflation(중간값 버리고 최신값만).
  • 유실 불가 데이터(채팅): 버리지 말고 끊은 뒤 seq 재전송으로 복구.
  • 반대 방향: 연결별 rate limit(토큰 버킷), 초과 시 1008.

더 깊이

COMMENTS (…)

댓글을 불러오는 중이에요.

NEW COMMENT0 / 1000
⌘↵ 전송

blog92@web:~$ cd ..