본문으로 건너뛰기

[sglang] SGLang Router의 버킷 기반 라우팅 및 KV Indexer 통합 최적화 분석

PR 링크: sgl-project/sglang#38108 상태: Merged | 변경: +5839 / -3636

들어가며

최근 SGLang 프로젝트의 Router 컴포넌트는 대규모 분산 추론 환경에서의 효율성을 극대화하기 위해 대대적인 구조 개선을 진행했습니다. 특히 기존의 cache_aware_zmq 정책을 제거하고, 버킷 기반의 도메인 라우팅과 외부 KV Indexer를 통합함으로써 캐시 적중률과 로드 밸런싱의 정교함을 한 단계 끌어올렸습니다. 본 글에서는 이 PR이 해결하고자 하는 문제와 핵심적인 코드 변경사항을 살펴봅니다.

코드 분석

1. 버킷 기반 도메인 라우팅 도입

기존에는 단일 도메인 내에서 라우팅이 이루어졌으나, 이제는 워커 그룹을 버킷 단위로 세분화하여 관리합니다.

// Before: 단일 도메인 기반의 단순 정책 적용
// After: 버킷 설정을 통한 도메인별 독립적 선택
let prefill_domain = select_prefill_domain(&buckets, request);
let decode_domain = select_decode_domain(&buckets, request);

이 변경을 통해 Prefill과 Decode 작업을 독립적인 도메인 내에서 최적화할 수 있게 되었으며, 특정 버킷의 제약 조건(토큰 범위, SLO 프로필 등)을 준수하면서도 유연한 리소스 할당이 가능해졌습니다.

2. 외부 KV Indexer 통합

로컬 Radix Tree에 의존하던 캐시 매칭 방식을 gRPC 기반의 외부 KV Indexer로 확장했습니다.

// Before: 로컬 Radix Tree 사용
// After: 외부 gRPC Indexer를 통한 캐시 매칭
--cache-prefix-provider indexer \
--kv-indexer-endpoint http://10.0.0.10:50051

이 방식은 대규모 클러스터에서 여러 Router 인스턴스가 동일한 KV 캐시 상태를 공유할 수 있게 하여, 캐시 적중률을 획기적으로 높입니다.

3. 용량 기반 Fallback 로직 개선

리뷰 과정에서 지적된 '첫 번째 버킷이 가득 찼을 때의 비효율성'을 해결하기 위해 2-pass 탐색 로직을 도입했습니다.

// 개선된 2-pass 탐색 로직
// 1단계: 모든 호환 가능한 버킷에서 가용 용량 확인
// 2단계: 용량 부족 시 Power-of-Two 기반 Fallback 적용
let candidates = find_admitted_candidates(buckets);
if candidates.is_empty() {
    return resolve_with_capacity_fallback(buckets);
}

왜 이게 좋은가

이번 최적화의 핵심은 '제약 조건의 명확한 분리''글로벌 캐시 가시성 확보'입니다.

  1. 성능 향상: 시뮬레이션 결과, 외부 KV Indexer를 사용했을 때 캐시 적중률이 크게 향상되었으며, 특히 대규모 워커 환경에서 Worker CV(Coefficient of Variation)를 낮추어 부하 분산이 훨씬 균형 있게 이루어짐을 확인했습니다.
  2. 운영 편의성: cache_aware_zmq와 같은 레거시 정책을 제거하고, 명시적인 버킷 설정을 도입함으로써 설정의 복잡도를 낮추고 디버깅 가능성을 높였습니다.
  3. 안정성: 리뷰어들의 피드백을 반영하여, 모든 버킷이 가득 찼을 경우에도 요청을 즉시 거부(503)하는 대신 Power-of-Two 기반의 Fallback을 수행하도록 하여 시스템의 가용성을 확보했습니다.

일반적인 교훈으로, 분산 시스템에서 라우팅 정책을 변경할 때는 '기존 정책과의 하위 호환성''실패 시의 안전장치(Fallback)'를 반드시 함께 설계해야 한다는 점을 다시 한번 확인했습니다.

참고 자료

⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.

댓글

관련 포스트

PR Analysis 의 다른글