🚀 【推理与部署篇03】SGLang深度解析:RadixAttention与结构化生成

2026年最新版 | 覆盖 SGLang v0.5.12+ | 400,000+ GPU 生产验证


📑 目录


1. SGLang核心架构与设计理念

1.1 什么是SGLang?

SGLang(Structured Generation Language)是由伯克利大学 LMSYS 实验室(LLM System)研发的新一代大模型推理引擎,定位不仅是推理加速器,更是一套完整的"大模型程序运行时"。

截至2026年5月,SGLang已在全球超过40万张GPU上部署,被 xAI、AMD、NVIDIA、Intel、LinkedIn、Cursor、Oracle Cloud 等顶级企业采用,GitHub 28K+ Stars,2026年已发布14个版本 [1]。

1.2 三层架构

┌──────────────────────────────────────────────┐
│  前端DSL层(sglang.xxx)                       │
│  - @sgl.function 装饰器 + sgl.gen / sgl.select │
│  - 结构化生成流、约束解码、工具调用             │
├──────────────────────────────────────────────┤
│  运行时层(Runtime)                           │
│  - RadixAttention 缓存管理                     │
│  - Overlap Scheduling 调度引擎                 │
│  - XGrammar 结构化输出后端                     │
│  - HiCache 三级缓存卸载                        │
├──────────────────────────────────────────────┤
│  内核层(Kernels)                             │
│  - FlashInfer Attention                        │
│  - Triton FP8 GEMM / DeepGemm MLA              │
│  - CUTLASS MoE Kernels                         │
│  - PD分离分布式协同                            │
└──────────────────────────────────────────────┘

1.3 设计哲学

与 vLLM 的"纯推理引擎"定位不同,SGLang 将编译器概念引入推理系统

维度 传统推理引擎 SGLang
定位 HTTP 服务 + 推理加速 程序运行时 + 推理加速
前端 OpenAI API 兼容 DSL 编程模型 + OpenAI API
缓存粒度 Page/Block 级 Token 级基数树
约束解码 外部工具(Outlines) 原生 XGrammar(零开销)
服务整合 需独立部署 LLM + VLM + Embedding 同一进程

2. RadixAttention原理深度解析

2.1 问题:传统前缀缓存的局限性

vLLM 的 Prefix Caching 基于哈希精确匹配:只有前缀完全一致才能复用缓存。在 RAG 或多轮对话中,不同请求的前缀往往部分相似(共享系统提示词但检索文档不同),哈希方案只能丢弃无法精确匹配的部分。

传统方案(vLLM Hash-based):
请求1: [系统提示词] + [文档A] + [问题]
请求2: [系统提示词] + [文档B] + [问题]
        ↓
请求1缓存: [系统提示词||文档A||问题] → 只能完整匹配
请求2: 系统提示词部分需重新计算 ❌

RadixAttention(SGLang):
请求1缓存:  ┌系统提示词┐┌文档A┐┌问题┐
请求2:      重用 ↑     计算新↑  重用↑
                              ↓
        系统提示词部分自动复用 ✅

2.2 基数树(Radix Tree)结构

RadixAttention 的核心数据结构是基数树,每个节点存储一段连续的 Token 序列 [2]:

Root
 ├── "System: You are a helpful assistant."
 │    ├── "What is the capital of France?" → "Paris"
 │    ├── "What is the capital of Japan?"  → "Tokyo"
 │    └── "Translate to French: Hello" → "Bonjour"
 ├── "System: You are a coding assistant."
 │    ├── "Write a Python function to..."
 │    └── "Explain the time complexity of..."
 └── "System: You are a data analyst."
      └── ...

关键特性

  • 最长公共前缀自动检测:新请求到达时,自动匹配已有树节点
  • Token 级粒度:节点按连续 token 序列组织,比 Page 级更精细
  • 部分复用:即使只有前缀部分匹配,也能复用共享节点
  • LRU 驱逐:缓存满时淘汰最近最少使用节点

2.3 完整实现

import threading
from typing import Dict, List, Optional, Tuple
import heapq

class RadixTreeNode:
    """基数树节点"""
    def __init__(self, token_ids: List[int]):
        self.token_ids = token_ids          # 节点存储的 token 序列
        self.children: Dict[int, 'RadixTreeNode'] = {}  # 子节点(首 token -> 节点)
        self.kv_cache: Optional[Tuple] = None  # 此节点对应的 KV Cache
        self.last_access_time: int = 0      # 最后访问时间(LRU)
        self.access_count: int = 0          # 访问次数
        self.is_leaf: bool = True

class RadixAttention:
    """
    RadixAttention 缓存管理器
    支持最长公共前缀匹配、部分复用、LRU驱逐
    """
    def __init__(self, max_cache_size: int = 100000):
        self.root = RadixTreeNode([])
        self.max_cache_size = max_cache_size
        self.current_size = 0
        self.lock = threading.Lock()
        self.access_counter = 0

    def match_prefix(self, token_ids: List[int]) -> Tuple[int, RadixTreeNode, List[RadixTreeNode]]:
        """
        匹配最长公共前缀
        返回:(匹配长度, 匹配到的节点, 路径上的节点列表)
        """
        node = self.root
        matched_len = 0
        path = [node]
        i = 0

        while i < len(token_ids):
            # 查找匹配的子节点
            first_token = token_ids[i]
            if first_token not in node.children:
                break

            child = node.children[first_token]
            # 检查子节点内的序列是否能匹配
            child_tokens = child.token_ids
            j = 0
            while j < len(child_tokens) and i < len(token_ids):
                if child_tokens[j] != token_ids[i]:
                    break
                j += 1
                i += 1

            if j > 0:
                matched_len += j
                path.append(child)
                node = child

                # 如果子节点的 token 没有完全匹配完,需要分裂
                if j < len(child_tokens):
                    self._split_node(child, j)
                    # 分裂后重新获取节点引用
                    child = node.children.get(token_ids[matched_len - j] if matched_len - j < len(token_ids) else None)
                    if child:
                        path[-1] = child
                continue
            break

        return matched_len, node, path

    def _split_node(self, node: RadixTreeNode, split_pos: int):
        """分裂节点:从 split_pos 处切开"""
        if split_pos <= 0 or split_pos >= len(node.token_ids):
            return

        # 新节点:保留后半部分
        new_node = RadixTreeNode(node.token_ids[split_pos:])
        new_node.kv_cache = None  # 分裂后需要重新计算
        new_node.children = node.children
        new_node.is_leaf = node.is_leaf

        # 原节点变为前半部分
        node.token_ids = node.token_ids[:split_pos]
        node.children = {new_node.token_ids[0]: new_node}
        node.is_leaf = False

        # 调整缓存大小
        self.current_size -= len(new_node.token_ids)

    def insert(self, token_ids: List[int], kv_cache: Tuple):
        """插入新的缓存序列"""
        with self.lock:
            # 先匹配已有前缀
            matched_len, node, path = self.match_prefix(token_ids)

            # 计算需要新插入的 token
            remaining = token_ids[matched_len:]
            if not remaining:
                # 完全命中已有节点,更新 KV Cache
                node.kv_cache = kv_cache
                node.last_access_time = self.access_counter
                node.access_count += 1
                self.access_counter += 1
                return

            # 逐段创建新节点
            current = node
            start = 0
            while start < len(remaining):
                # 尝试找到最大的可合并段
                end = start + 1
                while end <= len(remaining):
                    if self._is_mergeable(remaining[start:end]):
                        end += 1
                    else:
                        break
                end -= 1

                segment = remaining[start:end]
                new_node = RadixTreeNode(segment)
                new_node.last_access_time = self.access_counter
                self.access_counter += 1

                current.children[segment[0]] = new_node
                current.is_leaf = False
                current = new_node
                start = end

            # 最后的节点保存 KV Cache
            current.kv_cache = kv_cache
            current.is_leaf = True
            self.current_size += len(remaining)

            # LRU 驱逐
            while self.current_size > self.max_cache_size:
                self._evict_lru()

    def _is_mergeable(self, tokens: List[int]) -> bool:
        """判断一段 token 是否可以合并为单一节点(启发式)"""
        return len(tokens) <= 64  # 最大节点长度

    def _evict_lru(self):
        """LRU 驱逐:找到最久未访问的叶子节点并移除"""
        # BFS 找到最久未访问的叶子
        stack = [(self.root, 0)]
        oldest_node = None
        oldest_time = float('inf')

        while stack:
            node, depth = stack.pop()
            if node.is_leaf and node != self.root:
                if node.last_access_time < oldest_time:
                    oldest_time = node.last_access_time
                    oldest_node = node
            for child in node.children.values():
                stack.append((child, depth + 1))

        if oldest_node and oldest_node.kv_cache:
            self.current_size -= len(oldest_node.token_ids)
            oldest_node.kv_cache = None
            oldest_node.last_access_time = 0

    def get_cache(self, token_ids: List[int]) -> Optional[Tuple]:
        """获取匹配的 KV Cache"""
        matched_len, node, _ = self.match_prefix(token_ids)
        if node and node.kv_cache:
            node.last_access_time = self.access_counter
            node.access_count += 1
            self.access_counter += 1
            return node.kv_cache, matched_len
        return None, matched_len

    def get_cache_hit_rate(self) -> float:
        """计算缓存命中率"""
        total_nodes = 0
        cached_nodes = 0
        stack = [self.root]
        while stack:
            node = stack.pop()
            if node != self.root:
                total_nodes += 1
                if node.kv_cache is not None:
                    cached_nodes += 1
            for child in node.children.values():
                stack.append(child)
        return cached_nodes / max(total_nodes, 1)

2.4 实测效果

场景 缓存命中率 首Token延迟降低 吞吐提升
单用户 RAG (c=1) 92% 3.5× 2.8×
多轮对话 5轮 83% 28% 29%
Agent工具调用 78% 2.1× 1.8×
纯随机查询 12% 基准 基准

在共享前缀明显的场景(RAG、Agent 系统提示词、多轮对话),RadixAttention 相比 hash-based 方案有显著优势 [3]。

2.5 UnifiedRadixTree

SGLang v0.5.0+ 引入 UnifiedRadixTree,将传统 Radix Tree 与层级缓存结合:

GPU VRAM (最快, 最小)
  └── Radix Tree 热节点
       ↓ LRU 驱逐
CPU RAM (中等, 大)
  └── Radix Tree 温节点
       ↓ LRU 驱逐
SSD (最慢, 最大)
  └── 冷节点持久化

允许缓存远超 GPU 显存限制的 KV Cache,对长上下文服务至关重要。


3. XGrammar结构化生成

3.1 为什么需要结构化生成?

Agent 场景的核心需求:模型输出必须严格遵守 JSON Schema、正则表达式或 EBNF 语法。传统方案(先生成后验证):

传统方案:生成文本 → JSON解析 → 验证schema → 失败重试 ❌
                                      → 30%+ 重试率
XGrammar:约束解码 → 每一步只生成合法token ✅
                                      → 0 重试率

3.2 XGrammar 工作原理

XGrammar 是 SGLang 默认的结构化输出后端(2024.11 发布),实现零开销约束解码

用户定义 Schema
     ↓
XGrammar 编译为上下文无关文法 (CFG)
     ↓
在采样过程中实时计算合法 token 集合
     ↓
LM Head 输出概率 → 屏蔽非法 token → 采样

核心特性:

  • 编译时优化:Schema 预编译为 CFG,运行时零开销
  • token 级约束:每一步只采样合法 token
  • 支持格式:JSON Schema、正则表达式、EBNF、structural_tag
  • 多工具注册:一个请求内同时注册多个函数
import sglang as sgl

# === 方式1:@sgl.function 装饰器 DSL ===
@sgl.function
def extract_city_info(s, document):
    s += "从以下文档提取城市信息:\n"
    s += document + "\n"
    s += "输出 JSON:\n"
    s += "{\n"
    s += '  "name": ' + sgl.gen("name", max_tokens=8,
                                 regex=r'"[^"\\]*(?:\\.[^"\\]*)*"') + ",\n"
    s += '  "country": ' + sgl.gen("country", max_tokens=8,
                                    regex=r'"[^"\\]*(?:\\.[^"\\]*)*"') + ",\n"
    s += '  "latitude": ' + sgl.gen("latitude", max_tokens=8,
                                     regex=r'-?\d+\.\d+') + ",\n"
    s += '  "population": ' + sgl.gen("population", max_tokens=8,
                                       regex=r'-?\d+') + "\n"
    s += "}\n"

# === 方式2:OpenAI API 兼容(XGrammar structural_tag)===
response = client.chat.completions.create(
    model="qwen3-32b",
    messages=[{"role": "user", "content": "北京的天气怎么样?"}],
    response_format={
        "type": "structural_tag",
        "format": {
            "type": "triggered_tags",
            "triggers": ["<function="],
            "tags": [
                {
                    "begin": "<function=get_current_weather>",
                    "content": {
                        "type": "json_schema",
                        "json_schema": {
                            "type": "object",
                            "properties": {
                                "location": {"type": "string"},
                                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                            },
                            "required": ["location", "unit"]
                        }
                    },
                    "end": "</function>"
                },
                {
                    "begin": "<function=get_forecast>",
                    "content": {
                        "type": "json_schema",
                        "json_schema": {
                            "type": "object",
                            "properties": {
                                "location": {"type": "string"},
                                "days": {"type": "integer", "minimum": 1, "maximum": 7}
                            },
                            "required": ["location", "days"]
                        }
                    },
                    "end": "</function>"
                }
            ]
        }
    }
)

3.3 性能对比

指标 SGLang (XGrammar) vLLM + Outlines Guidance 提升倍数
吞吐量 (req/s) 36 12 8 3.0×
延迟 (ms) 28 83 125 4.5×
内存占用 (GB) 4.2 6.8 7.5 1.8×
准确率 (%) 98.7 95.2 93.8 +3.5%

4. Overlap Scheduling调度优化

4.1 传统调度瓶颈

LLM 推理的典型流程:

CPU: 接收请求 → 预处理(Tokenize) → 调度决策 → ...
                                    ↓ 等待
GPU:                     ← 执行推理 →

CPU 预处理和调度决策是同步阻塞的,GPU 在等待期间空闲。

4.2 Overlap Scheduling

SGLang 实现 CPU 和 GPU 的流水线重叠

传统调度:
GPU: ██████推理██████ ██████推理██████ ██████推理██████
CPU:                  准备下一批                   准备下一批
     ↑ GPU 空闲等待 ↑           ↑ GPU 空闲等待 ↑

Overlap Scheduling:
GPU: ██████推理██████ ██████推理██████ ██████推理██████
CPU:  准备下一批       准备下一批       准备下一批
                                               时间 →
     ↑ 零等待 ↑       ↑ GPU 始终满载 ↑

4.3 Zero-Overhead Batch Scheduler

SGLang v0.4+ 的 Zero-Overhead Batch Scheduler 进一步消除调度开销:

class OverlapScheduler:
    """
    CPU-GPU 重叠调度器
    在 GPU 执行当前批次时,CPU 预计算下一批
    """
    def __init__(self, max_batch_size: int = 256):
        self.max_batch_size = max_batch_size
        self.pending_queue = []       # 等待调度的请求
        self.running_batch = None     # 当前 GPU 执行批次
        self.next_batch = None        # 预计算的下一批

    def submit(self, request):
        """提交请求"""
        self.pending_queue.append(request)

    def schedule_async(self):
        """
        异步调度:在 GPU 空闲时预计算下一批
        此方法在 CPU 线程中异步执行
        """
        if self.next_batch is not None:
            return  # 已经预计算了下一批

        if not self.pending_queue:
            return

        # 批处理策略:优先相同长度的请求
        batch = []
        remaining = []
        ref_len = None

        for req in self.pending_queue:
            if ref_len is None:
                ref_len = len(req.input_ids)
                batch.append(req)
            elif abs(len(req.input_ids) - ref_len) / ref_len < 0.3:
                batch.append(req)
            else:
                remaining.append(req)

        self.pending_queue = remaining

        # 预计算:Tokenize、KV Cache 分配、调度决策
        self.next_batch = self._prepare_batch(batch)

        # 利用 RadixAttention 匹配缓存
        for req in self.next_batch:
            cache, matched = self.radix_cache.get_cache(req.input_ids)
            req.cached_prefix_len = matched

    def _prepare_batch(self, batch):
        """预计算批次元数据"""
        # 最大序列长度
        max_len = max(len(r.input_ids) for r in batch)

        processed = []
        for req in batch:
            processed.append({
                "input_ids": req.input_ids,
                "cached_prefix_len": 0,
                "prefill_len": len(req.input_ids),
                "decode_len": 0,
                "max_tokens": req.max_tokens,
                "sampling_params": req.sampling_params,
                "block_table": self._allocate_blocks(max_len + req.max_tokens),
            })

        return processed

    def step(self):
        """
        执行一步调度
        返回需要 GPU 执行的批次
        """
        if self.running_batch is None and self.next_batch is None:
            self.schedule_async()
            return None

        # 交换批次
        self.running_batch = self.next_batch
        self.next_batch = None

        # 异步预计算下一批
        self.schedule_async()

        return self.running_batch

实测效果:在低并发(c=1)场景下 Overlap Scheduling 可将 GPU 利用率从 65% 提升至 92%+ [4]。


5. PD分离与HiCache层级缓存

5.1 PD分离(Prefill-Decode Disaggregation)

预填充和解码阶段对资源需求完全不同:

维度 预填充(Prefill) 解码(Decode)
计算密集度 Compute-bound Memory-bound
并行度 高(一次性处理所有 token) 低(逐 token)
KV Cache 生成 写密集 读密集
理想硬件 高算力 GPU 高带宽 GPU

SGLang 支持将 Prefill 和 Decode 分配到不同 GPU:

请求到达
    ↓
Prefill GPU(高算力:H100/B300)
    ├── 计算完整 KV Cache
    ├── 通过 NCCL 传输
    ↓
Decode GPU(高带宽:H200/B300)
    ├── 复用已计算 KV Cache
    ├── 逐 token 生成
    ↓
返回结果

配置示例

# Prefill 节点(2 GPU)
python -m sglang.launch_server \
    --model-path Qwen/Qwen3-32B \
    --disaggregation-mode prefill \
    --tp 2 \
    --host 0.0.0.0 --port 30001

# Decode 节点(4 GPU)
python -m sglang.launch_server \
    --model-path Qwen/Qwen3-32B \
    --disaggregation-mode decode \
    --tp 4 \
    --host 0.0.0.0 --port 30002

# 路由节点
python -m sglang.launch_server \
    --model-path Qwen/Qwen3-32B \
    --disaggregation-mode router \
    --prefill-server http://prefill:30001 \
    --decode-server http://decode:30002 \
    --host 0.0.0.0 --port 8000

5.2 HiCache层级KV Cache卸载

HiCache 实现 GPU → CPU → SSD 三级缓存:

class HiCacheManager:
    """
    HiCache 层级缓存管理器
    支持 GPU VRAM → CPU RAM → SSD 三级卸载
    """
    def __init__(self, gpu_cache_size: int, cpu_cache_size: int,
                 ssd_cache_path: str):
        self.gpu_cache = {}        # GPU VRAM 缓存
        self.cpu_cache = {}        # CPU RAM 缓存
        self.ssd_cache_path = ssd_cache_path  # SSD 持久化
        self.gpu_limit = gpu_cache_size
        self.cpu_limit = cpu_cache_size

        # 访问频率跟踪
        self.access_stats = defaultdict(lambda: {"count": 0, "last_access": 0})

    def get(self, key: str) -> Optional[bytes]:
        """按优先级查找缓存"""
        if key in self.gpu_cache:
            self._update_stats(key)
            return self.gpu_cache[key]

        if key in self.cpu_cache:
            # 提升至 GPU(如果有空间)
            self._promote_to_gpu(key)
            self._update_stats(key)
            return self.cpu_cache[key]

        # 检查 SSD
        ssd_path = os.path.join(self.ssd_cache_path, key)
        if os.path.exists(ssd_path):
            data = self._read_ssd(ssd_path)
            # 提升至 CPU
            self._promote_to_cpu(key, data)
            self._update_stats(key)
            return data

        return None  # 缓存未命中

    def set(self, key: str, data: bytes):
        """写入缓存(写入 GPU)"""
        self._ensure_gpu_space(data)
        self.gpu_cache[key] = data
        self._update_stats(key)

    def _ensure_gpu_space(self, data: bytes):
        """确保 GPU 有足够空间,不够则驱逐到 CPU/SSD"""
        current_size = sum(len(v) for v in self.gpu_cache.values())
        if current_size + len(data) <= self.gpu_limit:
            return

        # 按访问频率排序驱逐
        evict_candidates = sorted(
            self.gpu_cache.keys(),
            key=lambda k: self.access_stats[k]["count"]
        )

        for key in evict_candidates:
            if current_size + len(data) <= self.gpu_limit:
                break

            # 驱逐到 CPU
            self._evict_to_cpu(key)
            current_size -= len(self.gpu_cache.pop(key))

    def _evict_to_cpu(self, key: str):
        """GPU → CPU 驱逐"""
        if key not in self.gpu_cache:
            return
        self._ensure_cpu_space(self.gpu_cache[key])
        self.cpu_cache[key] = self.gpu_cache[key]

    def _promote_to_gpu(self, key: str):
        """CPU → GPU 提升"""
        if key not in self.cpu_cache:
            return
        self._ensure_gpu_space(self.cpu_cache[key])
        self.gpu_cache[key] = self.cpu_cache.pop(key)

    def _update_stats(self, key: str):
        self.access_stats[key]["count"] += 1
        self.access_stats[key]["last_access"] = time.time()

6. 多模态与Embedding统一服务

6.1 统一服务架构

SGLang 的一大特色是可以用同一个服务进程同时处理:

  • 纯文本 LLM 推理
  • 多模态 VLM 推理(Qwen-VL、LLaVA、MiniCPM-V、NVILA)
  • Embedding 向量化(Qwen3-Embedding、GME)
  • 重排序(Reranker)
# 一个服务,全部支持
python -m sglang.launch_server \
    --model-path Qwen/Qwen3.6-VL-32B \
    --host 0.0.0.0 --port 8000

# 客户端统一调用
import sglang as sgl

# LLM 文本生成
response = sgl.chat("Hello, how are you?")

# VLM 多模态
response = sgl.chat(
    "这张图片里有什么?",
    images=["https://example.com/photo.jpg"]
)

# Embedding
embeddings = sgl.embed(["文本1", "文本2"])

# 同一个进程,无需部署多套服务

6.2 模型支持矩阵(v0.5.12)

模型类型 支持模型 支持程度
LLM Qwen3/3.5/3.6, LLaMA 4, Gemma 4, DeepSeek V4 原生支持
VLM Qwen-VL, LLaVA 1.6, MiniCPM-V, NVILA 原生支持
Embedding Qwen3-Embedding, GME, BGE 原生支持
MoE DeepSeek V4, MiniMax-M2.5, Qwen3.5-MoE Triton MoE Runner

7. 性能基准测试

7.1 标准 Benchmark(H100)

引擎 模型 精度 吞吐量 (tok/s) 对比 vLLM
SGLang LLaMA 3.1 8B BF16 16,215 +29%
LMDeploy LLaMA 3.1 8B BF16 16,132 +28%
vLLM LLaMA 3.1 8B BF16 12,553 baseline

数据来源:AIMultiple 2026-04 基准测试 [5]。即使在相同 kernel(FlashInfer)下,SGLang 的调度层优化带来了 29% 吞吐优势。

7.2 RTX PRO 6000 Blackwell 实测

引擎 模型格式 峰值吞吐 备注
vLLM NVFP4 8,033 tok/s 整体最高
SGLang GPTQ-INT4 6,395 tok/s +17% vs vLLM GPTQ
vLLM GPTQ-INT4 ~5,470 tok/s 同精度对比
Ollama INT4 484 tok/s ~10× 慢

同精度(GPTQ-INT4)下 SGLang 领先 17% [6]。

7.3 TTFT 首Token延迟对比

场景 SGLang vLLM 胜出
RAG 单用户 (c=1) 597ms 2,081ms SGLang 3.5×
RAG 多用户 (c=20) 2,593ms 2,172ms vLLM
Dual H100 (c=1) 583ms 2,141ms SGLang 3.7×
Dual H100 (c=100) 2,775ms 2,843ms 持平

7.4 高并发P95尾延迟

引擎 128并发成功率 P95延迟
SGLang 100% P95 ≈ 1.2-1.4× 中位数
vLLM 100% P95 可达 9-12× 中位数

SGLang 在高并发下延迟分布更稳定,P95 尾延迟仅为中位数的 1.2-1.4 倍,而 vLLM 可达 9-12 倍 [3]。


8. 生产部署最佳实践

8.1 基础 Docker 部署

# 拉取 SGLang 官方镜像
docker pull lmsysorg/sglang:v0.5.12.post1

# 启动服务
docker run --gpus all \
    --shm-size 32g \
    -p 8000:8000 \
    -v ~/.cache/huggingface:/root/.cache/huggingface \
    lmsysorg/sglang:v0.5.12.post1 \
    python -m sglang.launch_server \
    --model-path Qwen/Qwen3-32B \
    --host 0.0.0.0 \
    --port 8000 \
    --mem-fraction-static 0.90 \
    --max-num-seqs 256 \
    --enable-mix-precision fp16

8.2 Kubernetes 生产部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sglang-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sglang
  template:
    metadata:
      labels:
        app: sglang
    spec:
      containers:
      - name: sglang
        image: lmsysorg/sglang:v0.5.12.post1
        command:
        - python
        - -m
        - sglang.launch_server
        args:
        - --model-path
        - Qwen/Qwen3-32B
        - --host
        - 0.0.0.0
        - --port
        - "8000"
        - --mem-fraction-static
        - "0.90"
        - --max-num-seqs
        - "256"
        - --enable-metrics
        ports:
        - containerPort: 8000
        resources:
          limits:
            nvidia.com/gpu: 2
          requests:
            nvidia.com/gpu: 2
        volumeMounts:
        - name: model-cache
          mountPath: /root/.cache
        - name: shared-memory
          mountPath: /dev/shm
      volumes:
      - name: model-cache
        persistentVolumeClaim:
          claimName: model-cache-pvc
      - name: shared-memory
        emptyDir:
          medium: Memory
---
apiVersion: v1
kind: Service
metadata:
  name: sglang-service
spec:
  selector:
    app: sglang
  ports:
  - port: 8000
    targetPort: 8000
  type: ClusterIP
---
# HPA:基于 GPU 利用率和请求延迟自动扩缩
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: sglang-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sglang-server
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: sglang_gpu_utilization
      target:
        type: AverageValue
        averageValue: 80
  - type: Pods
    pods:
      metric:
        name: sglang_request_latency_p99
      target:
        type: AverageValue
        averageValue: 2000  # 2秒

8.3 Prometheus + Grafana 监控

SGLang 原生暴露 Prometheus 指标:

# prometheus-scrape-config.yaml
scrape_configs:
- job_name: 'sglang'
  scrape_interval: 10s
  static_configs:
  - targets:
    - 'sglang-service:8000'
  metrics_path: '/metrics'

关键监控指标:

指标名 类型 说明
sglang_num_running_reqs Gauge 当前运行请求数
sglang_num_waiting_reqs Gauge 等待队列长度
sglang_cache_hit_rate Gauge RadixAttention 缓存命中率
sglang_throughput_token_s Gauge 每秒输出 token 数
sglang_ttft_ms Histogram 首 token 延迟分布
sglang_tpot_ms Histogram 每 token 延迟分布
sglang_gpu_mem_usage_gb Gauge GPU 显存使用
sglang_prefix_match_len Histogram 前缀匹配长度分布

Grafana 告警规则:

groups:
- name: sglang_alerts
  rules:
  - alert: HighLatency
    expr: sglang_ttft_ms{quantile="0.99"} > 5000
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "SGLang P99 latency > 5s"

  - alert: LowCacheHitRate
    expr: sglang_cache_hit_rate < 0.3
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "RadixAttention cache hit rate below 30%"

  - alert: GPUMemoryPressure
    expr: sglang_gpu_mem_usage_gb > 75
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "GPU memory > 75GB"

9. 关键参数调优指南

9.1 显存与批处理

参数 默认值 推荐值 说明
--mem-fraction-static 0.85 0.88-0.95 GPU 显存使用比例,H100 可设 0.95
--max-num-seqs 64 128-512 最大并发序列数,高并发增大
--context-length 4096 模型支持的最大长度 上下文窗口大小
--kv-cache-dtype auto fp8_e4m3 KV Cache 精度,H100 推荐 fp8

9.2 缓存与调度

参数 默认值 推荐值 说明
--enable-radix-cache True True 启用 RadixAttention
--enable-metrics False True 启用 Prometheus 指标
--schedule-policy lpm lpm 调度策略(lpm/lof/random)
--chunked-prefill-size 8192 4096-16384 分块预填充大小

9.3 分布式

参数 默认值 推荐值 说明
--tp 1 2-8 Tensor Parallel 大小
--dp 1 2-4 Data Parallel 大小
--ep-size 1 等于 num_experts Expert Parallel 大小
--nccl-init-addr localhost 实际 IP NCCL 初始化地址

9.4 解码与采样

参数 默认值 推荐值 说明
--speculative-algorithm None eagle3/draft_model 投机解码算法
--speculative-draft-model None 同系列小模型 草稿模型路径
--default-sampling-params {} 按需设置 默认采样参数

9.5 SM120(Blackwell)兼容配置

# Blackwell SM120 MoE 模型兼容启动
SGLANG_DISABLE_DEEP_GEMM=1 \
python -m sglang.launch_server \
    --model-path MiniMax-M2.5-228B \
    --fp8-gemm-backend triton \
    --moe-runner-backend triton \
    --kv-cache-dtype fp8_e4m3 \
    --mem-fraction-static 0.85

10. SGLang vs vLLM选型决策

10.1 全维度对比(2026年5月)

维度 SGLang v0.5.12 vLLM v0.21.0 胜出
GitHub Stars 28K 81K vLLM
全球GPU部署 400K+ 更广泛 vLLM
缓存机制 RadixAttention (基数树) Hash-based SGLang
结构化输出 XGrammar (默认, 零开销) XGrammar 0.2.0 SGLang
多模态支持 原生 (Qwen-VL/LLaVA/MiniCPM) 支持 SGLang
离线吞吐 +29% vs vLLM 基准 SGLang
P95尾延迟 1.2-1.4× 中位数 9-12× 中位数 SGLang
RAG单用户TTFT 3.5× 更快 基准 SGLang
社区生态 快速增长 成熟稳定 vLLM
文档质量 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ vLLM
API兼容性 OpenAI 完全兼容 OpenAI 完全兼容 持平

10.2 场景推荐

你的场景
 │
 ├── 多轮对话 / 客服机器人 → SGLang ✅
 ├── RAG知识库问答         → SGLang ✅(RadixAttention优势)
 ├── Agent工具调用         → SGLang ✅(XGrammar + structural_tag)
 ├── 结构化JSON输出        → SGLang ✅(3倍加速)
 ├── 多模态统一服务        → SGLang ✅(同一进程)
 ├──
 ├── 高并发短请求          → vLLM ✅
 ├── 长文本生成            → vLLM ✅(PagedAttention成熟)
 ├── 已有vLLM生态          → vLLM ✅
 ├── 快速搭建Demo          → vLLM ✅(文档丰富)
 └── 社区/第三方集成优先    → vLLM ✅

10.3 混合部署策略

生产环境中,推荐根据场景混合使用

请求入口 → 路由层
  ├── RAG/Agent/多轮对话 → SGLang 集群
  │   ├── RadixAttention + XGrammar
  │   └── 统一服务 (LLM + VLM + Embedding)
  │
  └── 批量推理/长文本 → vLLM 集群
      ├── PagedAttention + Chunked Prefill
      └── 成熟批处理调度

📌 面试加分点

1️⃣ RadixAttention vs PagedAttention 核心区别

PagedAttention RadixAttention
灵感来源 操作系统内存分页 基数树数据结构
缓存粒度 Page/Block 级别 Token 级别
跨请求复用 精确哈希匹配 最长公共前缀自动检测
部分复用
显存利用率 95%+ 92%+
共享前缀场景 一般 优秀

2️⃣ 结构化生成的三种实现路径

  1. Grammar-based(XGrammar):编译 Schema 为 CFG,采样时动态屏蔽非法 token —— 零开销
  2. Logit 掩码:在 logits 层手动 mask 非法 token —— 需自定义 kernel
  3. 后处理重试:生成后再解析验证 —— 30%+ 重试率,最低效

3️⃣ SGLang 核心优化流水线

请求到达
  ↓
RadixAttention 前缀匹配 → 缓存命中则跳过重复计算
  ↓
Overlap Scheduling → CPU 预计算下一批(GPU 零等待)
  ↓
XGrammar 约束解码 → 每一步屏蔽非法 token
  ↓
FlashInfer Attention → 高效注意力计算
  ↓
FP8/Triton Kernel → 混合精度加速
  ↓
HiCache 层级缓存 → GPU→CPU→SSD 三级卸载

4️⃣ SGLang 性能调优口诀

“缓存看命中,显存定并发,量化选精度,分离治长文”

  • 缓存命中率 < 30% → 检查 RadixAttention 配置或调整请求结构
  • GPU 显存利用率 < 80% → 增大 --mem-fraction-static--max-num-seqs
  • 小型模型(<20B)→ 优先 BF16 而非量化
  • 大型模型(>70B)→ PD 分离 + FP8 量化
  • 长上下文场景 → 启用 HiCache 层级卸载

参考来源

  1. SGLang vs vLLM 深度对比 (2026-05-30) — Joshua8.AI
  2. SGLang RadixAttention 技术实现 — GitCode Blog
  3. SGLang vs vLLM 实战评测:多轮对话场景下吞吐量对比 — CSDN Blog
  4. SGLang Overlap Scheduling 技术要点 — AICon
  5. AIMultiple Inference Engine Benchmark (2026-04)
  6. Joshua8.AI Blackwell Benchmark (2026-01)
  7. SGLang 官方文档 — docs.sglang.io
  8. vLLM 官方文档 — docs.vllm.ai
Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐