14. 로드 밸런싱: L4 vs L7, 세션 어피니티, 일관 해싱, 헬스체크
난이도 중난이도: 중
1. L4 vs L7
L4(전송 계층) LB는 IP·포트(TCP/UDP 헤더)만 보고 패킷/연결을 백엔드로 넘긴다. 페이로드를 해석하지 않으므로 빠르고 가볍고, 한 연결을 그대로 한 백엔드에 핀(pin)한다. NAT 방식 또는 DSR 방식으로 동작한다. L7(응용 계층) LB는 연결을 종단(terminate)해 내용을(HTTP 경로/헤더/쿠키, TLS SNI 등) 파싱한 뒤 라우팅한다. 경로 기반 라우팅·쿠키 스티키·요청 단위 재시도·헤더 조작이 가능하지만, 연결 종단·복호화 비용이 크고 지연이 는다.
실시간 게임은 하나의 장수명 TCP(또는 UDP) 연결 위에서 바이너리 프로토콜을 주고받는다. 요청 단위 L7 라우팅이 줄 이점(경로/쿠키 분기)이 거의 없고, 연결을 한 백엔드에 고정하는 것이 핵심이므로 L4가 더 자연스럽다(특히 UDP/커스텀 프로토콜). 단 초기 접속(웹 로그인·매치메이킹 REST API)은 L7으로 두는 하이브리드가 흔하다.
2. 분배 알고리즘
- 라운드로빈: 순서대로 분배. 단순하지만 서버 성능차·연결 수명차를 무시한다.
- 가중 라운드로빈: 서버 용량에 가중치. 이기종 하드웨어에 유용.
- 최소 연결(least connections): 현재 활성 연결이 가장 적은 곳으로. 연결 수명이 제각각인 게임(어떤 세션은 몇 시간)에서 라운드로빈보다 균형이 좋다.
- IP/해시 기반: 클라 IP(또는 5-튜플) 해시로 백엔드 결정 → 같은 클라가 같은 서버로(스티키 효과). 단
hash % N은 서버 수 N이 바뀌면 거의 모든 키가 재배치된다. - 일관 해싱: 서버와 키를 같은 해시 링(0~2^k)에 올리고, 키는 시계방향 첫 서버로 간다. 서버 하나가 빠지면 그 서버가 맡던 구간만 다음 서버로 넘어가고 나머지는 그대로 → 평균 K/N 키만 이동(
hash % N은 거의 전부 이동). 가상 노드(vnode)를 여러 개 두어 부하 균형과 핫스팟을 완화한다. 캐시 샤딩·세션 라우팅·분산 저장의 표준 기법.
3. 세션 어피니티(sticky)
게임 세션은 서버 메모리에 상태(캐릭터, 방, 큐, 송수신 버퍼)를 들고 있다. 매 패킷이 다른 서버로 가면 그 상태를 못 찾으므로, 한 연결은 같은 백엔드로 계속 가야 한다. 구현:
- 5-튜플 해시(L4): (출발 IP/포트, 목적 IP/포트, 프로토콜) 해시로 연결을 한 백엔드에 고정. 연결 단위라 자연 스티키.
- L7 쿠키: LB가 백엔드를 가리키는 쿠키를 심어 같은 곳으로(웹/HTTP에 적합, 바이너리 게임 프로토콜엔 부적합).
- 일관 해싱: 클라 키(계정 ID 등)를 링에 매핑.
한계: 어느 방식이든 서버 증설/축소 시 일부 키가 재배치되어 그 세션은 끊겨 재접속이 필요하다. 그래서 상태를 외부(Redis/DB)에 두거나, 재접속 토큰으로 빠르게 복구하거나, 드레이닝으로 점진 이동시키는 보완이 필요하다. 스티키는 "상태 지역성"을 주는 대신 유연한 재분배·완벽한 부하 균형과 상충한다.
4. 헬스체크와 드레이닝
- 액티브 헬스체크: LB가 주기적으로
/health·TCP 핸드셰이크·핑을 보내 응답/지연으로 정상 판정. 임계 실패 시 풀에서 제외, 회복되면 복귀. - 패시브(아웃라이어 감지): 실제 트래픽의 오류율/타임아웃을 관찰해 비정상 노드를 자동 격리(서킷브레이커와 결합). 액티브가 못 잡는 부분 장애를 잡는다.
- 드레이닝/graceful: 배포·축소 시 노드를 곧장 끊지 않고 신규 연결만 끊고 기존 연결은 끝날 때까지 유지한다. 게임은 세션이 길어 강제 종료가 곧 유저 이탈이므로, "더 이상 새 매칭을 받지 않음(drain) → 진행 중 전투 종료 대기 → 비우기 → 종료" 순서가 중요하다. 헬스체크가 드레이닝 중 노드를 빠르게 빼되 in-flight는 보존하도록 조율한다.
5. 게임 특유의 고려
stateless HTTP는 어떤 요청이든 아무 서버가 처리 가능해 LB가 자유롭게 분배한다. 반면 게임 게이트웨이/매치메이커는 상태가 특정 서버에 묶여 있다. 그래서:
- 접속/매칭 트래픽은 LB(L4)로 가용 게이트웨이에 분산하되, 일단 붙으면 스티키로 고정.
- "방·인스턴스·존을 특정 서버가 소유" 하는 트래픽은 LB의 부하 기준 분배가 아니라 디렉터리/라우팅 테이블 기반 라우팅으로 보내야 한다. 예: "이 던전 인스턴스는 노드 7이 호스팅" → 해당 플레이어 패킷은 부하와 무관하게 노드 7로. 매치메이커가 방을 만들 때 어느 노드가 소유할지 정하고 그 매핑을 디렉터리(서비스 디스커버리/레지스트리)에 등록한다.
- DSR(Direct Server Return): 응답 패킷이 LB를 거치지 않고 백엔드→클라로 직접 나간다. 게임은 다운스트림(서버→클라) 트래픽이 크므로, LB가 인바운드만 처리하고 아웃바운드를 우회시키면 LB 대역폭 병목을 크게 줄인다.
요약하면, 게임 LB의 핵심 긴장은 "부하 균형(자유 재분배)" vs "상태 지역성(스티키·소유 라우팅)" 이며, L4 스티키 + 외부 상태/재접속 + 소유 기반 디렉터리 라우팅 + 드레이닝을 조합해 균형을 잡는다.