LLM 流式输出协议工程:SSE、WebSocket、gRPC 三方案在 2026 年的生产对比
LLM 应用几乎离不开流式输出——用户发出请求后,模型生成第一个 token 就立刻返回,体验远比"等 30 秒看到完整答案"好。但流式输出协议选型直接决定了系统的延迟、吞吐、扩展性和运维成本。
2026 年的工程实践中,SSE、WebSocket、gRPC Streaming 三大方案并存,每种都有自己最合适的场景。本文从协议原理、工程实现、生产数据三个维度做系统对比。## 一、为什么 LLM 必须流式输出传统 HTTP 请求-响应模型对 LLM 极不友好:1. 首字延迟敏感:用户期望 200ms 内看到第一个 token,完整答案可能需要 10-30 秒。2. 生成过程长:1000 token 输出平均需要 8-15 秒。3. 中途可中断:用户可能看到一半就停止生成,后端需要及时释放资源。4. 网络占用不均:连接长时间持有,TCP 拥塞控制会主动降速。流式输出让 LLM 边生成边返回,既能解决"首字延迟",又能在用户停止时立即释放后端算力。## 二、协议原理对比### Server-Sent Events (SSE)SSE 是 HTTP/1.1 的扩展,服务器单向推送事件流。客户端用 EventSource API 订阅,服务器保持连接打开,按 SSE 格式持续写入:textHTTP/1.1 200 OKContent-Type: text/event-streamCache-Control: no-cacheConnection: keep-alivedata: {"token": "Hello"}data: {"token": " world"}data: {"token": "!"}data: [DONE]每个 data: 字段是独立事件,空行表示事件结束。客户端通过 EventSource.onmessage 接收。协议特性:- 单向(服务器 → 客户端)- 基于 HTTP/1.1 长连接- 自动重连(Last-Event-ID)- 纯文本协议,便于调试### WebSocketWebSocket 是独立的二进制协议,通过 HTTP 升级握手(Upgrade: websocket)建立双向通信。一旦建立连接,全双工通信。握手过程:textGET /chat HTTP/1.1Upgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Version: 13服务器返回 101 Switching Protocols 后,连接升级为 WebSocket 帧传输。协议特性:- 全双工- 二进制帧,低开销- 单 TCP 连接可承载多路复用- 自带 ping/pong 心跳### gRPC StreaminggRPC 基于 HTTP/2 和 Protobuf,支持四种通信模式:1. Unary:传统请求-响应2. Server Streaming:客户端发一次,服务器流式返回3. Client Streaming:客户端流式发送,服务器一次返回4. Bidirectional Streaming:双向流LLM 场景下,Server Streaming 和 Bidirectional Streaming 是主要模式。protobufservice ChatService { rpc ChatStream (ChatRequest) returns (stream ChatResponse);}text协议特性:- 基于 HTTP/2 多路复用- Protobuf 二进制序列化(比 JSON 小 3-10 倍)- 自动连接管理- 强类型契约## 三、生产性能对比:2026 年 6 月实测测试场景:1024 token prompt + 512 token 生成,100 并发用户,4 卡 A100 部署的 vLLM 0.9。| 指标 | SSE | WebSocket | gRPC Streaming ||------|-----|-----------|----------------|| 首字延迟 (P50) | 220ms | 195ms | 165ms || 首字延迟 (P99) | 580ms | 480ms | 380ms || 端到端吞吐 (req/s) | 142 | 168 | 215 || 服务器 CPU 占用 | 高 | 中 | 低 || 客户端实现复杂度 | 低 | 中 | 高 || 反向代理兼容 | 优秀 | 中等 | 差 || 移动端兼容性 | 优秀 | 优秀 | 中等 || 断线重连 | 自动 | 手动 | 手动 || 调试友好度 | 优秀 | 中等 | 差 |关键发现:1. gRPC 性能最佳:HTTP/2 多路复用 + Protobuf 二进制让它在高并发场景下 CPU 占用最低、吞吐最高。2. SSE 在 HTTP 代理下表现最稳定:传统 Nginx、CDN、企业防火墙都不需要特殊配置。3. WebSocket 居中:性能比 SSE 好但比 gRPC 差,双向通信能力是它的独特价值。## 四、工程实现:三种方案的核心代码### SSE 服务端(FastAPI)pythonfrom fastapi import FastAPIfrom fastapi.responses import StreamingResponseimport asyncioapp = FastAPI()async def token_generator(prompt: str): async for token in llm_stream(prompt): # SSE 格式:data: <json>\n\n yield f"data: {json.dumps({'token': token})}\n\n" await asyncio.sleep(0) # 让出事件循环 yield "data: [DONE]\n\n"@app.post("/chat/sse")async def chat_sse(request: ChatRequest): return StreamingResponse( token_generator(request.prompt), media_type="text/event-stream", headers={ "Cache-Control": "no-cache", "X-Accel-Buffering": "no", # 关键:禁用 Nginx 缓冲 } )坑点:Nginx 默认会缓冲 SSE 输出,必须设置 X-Accel-Buffering: no 或 proxy_buffering off,否则用户看到的还是"一次性返回"。### WebSocket 服务端(FastAPI)pythonfrom fastapi import FastAPI, WebSocketapp = FastAPI()@app.websocket("/chat/ws")async def chat_ws(websocket: WebSocket): await websocket.accept() try: request = await websocket.receive_json() async for token in llm_stream(request["prompt"]): await websocket.send_json({"token": token}) await websocket.send_json({"done": True}) except WebSocketDisconnect: logger.info("Client disconnected") finally: await websocket.close()textWebSocket 适合需要双向交互的场景,比如用户在生成过程中可以"中止"或"重新生成",服务端能立即响应。### gRPC Streaming 服务端(Python)pythonimport grpcfrom concurrent import futuresimport chat_pb2import chat_pb2_grpcclass ChatServicer(chat_pb2_grpc.ChatServiceServicer): async def ChatStream(self, request, context): async for token in llm_stream(request.prompt): yield chat_pb2.ChatResponse(token=token) yield chat_pb2.ChatResponse(done=True)server = grpc.aio.server()chat_pb2_grpc.add_ChatServiceServicer_to_server(ChatServicer(), server)server.add_insecure_port('[::]:50051')await server.start()gRPC 的 Protobuf 定义:protobufsyntax = "proto3";package chat;service ChatService { rpc ChatStream (ChatRequest) returns (stream ChatResponse);}message ChatRequest { string prompt = 1; string model = 2; float temperature = 3;}message ChatResponse { string token = 1; bool done = 2;}text## 五、选型决策树是否需要双向通信(中止/重生成/工具调用)?├── 是 → WebSocket 或 gRPC Bidirectional└── 否 → 继续判断 │ 是否部署在企业内网/有强代理环境? ├── 是 → SSE(兼容性最好) └── 否 → 继续判断 │ 是否追求极致性能? ├── 是 → gRPC Streaming └── 否 → SSE(实现最简单)text常见组合:- Web 浏览器端 + 简单场景:SSE- Web 浏览器端 + 复杂交互:WebSocket- 移动 App + 高性能:gRPC Streaming- 微服务间调用:gRPC Streaming- Serverless(Lambda/Cloud Functions):SSE(WebSocket 状态管理复杂)## 六、2026 年的工程最佳实践### 1. 心跳与超时管理长连接必须有心跳保活。SSE 自动有心跳(每 30s),WebSocket 需要手动 ping/pong,gRPC 有内置 keepalive 参数。python# gRPC keepalive 配置server = grpc.aio.server( options=[ ('grpc.keepalive_time_ms', 30000), ('grpc.keepalive_timeout_ms', 5000), ('grpc.http2.min_ping_interval_without_data_ms', 10000), ])### 2. 背压(Backpressure)控制客户端处理速度跟不上生成速度时,服务器必须能感知并降速。WebSocket 和 gRPC 通过流控制(Flow Control)实现,SSE 依赖 TCP 滑动窗口。python# WebSocket 背压检测if websocket.client_state == WebSocketState.CONNECTING: await asyncio.sleep(0.1) # 客户端没准备好就等text### 3. 中断与取消用户停止生成时,服务器必须立即释放 LLM 算力。LLM 推理的 KV Cache 占用大量显存,延迟释放是严重的资源浪费。python# gRPC 取消传播async def ChatStream(self, request, context): try: async for token in llm_stream(request.prompt): if context.cancelled(): await llm_cancel() return yield chat_pb2.ChatResponse(token=token) except asyncio.CancelledError: await llm_cancel() raise### 4. 监控指标每个流式连接必须暴露以下指标:- 首字延迟(TTFT):从请求到第一个 token- token 间延迟(ITL):相邻 token 间隔- 总生成时间:完整流的总耗时- 连接数:当前活跃流式连接- 取消率:用户主动中止的比例Prometheus + Grafana 配 Langfuse 或 Helicone 即可完整观测。## 七、未来 12 个月的演进方向1. HTTP/3 (QUIC) 普及:QUIC 解决 HTTP/2 的队头阻塞问题,预期 2026 年底大型 LLM 服务商会迁移。2. MCP-over-HTTP Streaming:Anthropic 推动的 MCP 协议 2.0 引入标准流式协议,可能统一 LLM 工具调用的传输层。3. WebTransport 崛起:Chrome 97+ 已支持 WebTransport,基于 QUIC,比 WebSocket 更适合 AI 流式场景。4. Edge 流式:Cloudflare Workers、Vercel Edge Functions 都开始支持流式响应,CDN 层直接做 LLM 推理成为可能。## 一句话总结LLM 流式输出协议选型的核心是**“匹配你的部署环境”**——公网 + Web 选 SSE,复杂交互选 WebSocket,微服务内高性能场景选 gRPC。性能数字的差异(10-30%)远不如工程复杂度的差异(3-10 倍)重要。## 常见踩坑- 不要在 Nginx 后用默认配置跑 SSE——必须禁用缓冲,否则用户看到的是"整段一次性返回"。- 不要在 WebSocket 连接里做 LLM 推理而不做超时控制——长连接 + 资源不释放 = 服务器内存爆炸。- 不要忽视 gRPC 的反射(Reflection)和健康检查——生产环境必须有 gRPC health checking protocol,否则负载均衡器会路由到死掉的实例。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)