大模型 API 设计:RESTful、gRPC 还是 WebSocket?
大模型 API 设计:RESTful、gRPC 还是 WebSocket?
引言
当你构建一个面向大语言模型(LLM)的服务时,API 的设计直接决定了系统的延迟、吞吐量、流式能力和客户端集成的便捷性。本教程将从零开始,对比 RESTful、gRPC 和 WebSocket 三种主流通信协议在大模型场景下的表现,帮助你做出最适合业务需求的技术选型。
大模型 API 设计的核心挑战
与传统的 CRUD 接口不同,大模型推理具有以下特殊性:
- 高延迟与流式输出:单次生成可能耗时数秒甚至数十秒,用户需要实时看到逐 token 的输出。
- 长连接与状态管理:对话场景需要维护会话上下文,单次请求可能包含多轮对话。
- 高吞吐与低资源消耗:GPU 资源昂贵,需要高效利用连接和传输带宽。
- 多模态扩展:未来可能传输图像、音频等大型二进制数据。
- 客户端多样性:从浏览器到移动端再到嵌入式设备,要求协议具有广泛的兼容性。
理解这些挑战后,我们再分别审视 RESTful、gRPC 和 WebSocket 的能力边界。
RESTful API:经典之选
REST (Representational State Transfer) 是基于 HTTP 协议的架构风格,使用标准方法 (GET, POST, PUT, DELETE) 操作资源。其无状态、可缓存、统一接口的特性使其成为 Web 服务的“通用语言”。
在大模型中的应用
OpenAI 的 Chat Completions API 就是典型的 RESTful 设计:
POST https://api.openai.com/v1/chat/completions
Authorization: Bearer sk-...
Content-Type: application/json
{
"model": "gpt-4",
"messages": [{"role": "user", "content": "你好"}],
"stream": false
}
当 stream: false 时,服务端一次性返回完整结果;当 stream: true 时,响应头设置 Transfer-Encoding: chunked,以 Server-Sent Events (SSE) 形式逐块推送 token。
优点
- 生态成熟:所有编程语言都有成熟的 HTTP 客户端,调试工具 (curl, Postman) 丰富。
- 无状态易于扩展:负载均衡器天然支持,水平扩展简单。
- 可缓存性:对于确定性结果可设置缓存,降低模型调用成本。
- 安全基础设施:TLS、OAuth2、限流等可直接复用现有网关。
缺点
- 流式实现依赖非标准模式:标准 REST 是请求-响应模型,流式需要 SSE 或 WebSocket 辅助,增加了复杂度。
- 头部开销大:每次请求都携带完整的 HTTP 头,在长连接场景下效率较低。
- 二元数据不便:虽然支持 Base64 编码,但传输大尺寸的图片或向量时效率较差。
- 缺乏强类型契约:接口定义松散,需要额外文档说明字段语义。
gRPC:高性能二进制协议
gRPC 是 Google 开发的高性能远程过程调用框架,基于 HTTP/2 传输,使用 Protocol Buffers(protobuf)作为接口定义语言和序列化格式。它原生支持单工、双工流式通信。
在大模型中的应用
TensorFlow Serving 和 NVIDIA Triton Inference Server 都优先提供 gRPC 接口。定义一个简单的推理服务:
service LLMService {
rpc Chat(ChatRequest) returns (stream ChatResponse);
rpc Generate(GenerateRequest) returns (GenerateResponse);
}
message ChatRequest {
string model = 1;
repeated Message messages = 2;
}
message ChatResponse {
string token = 1;
}
通过 .proto 文件,自动生成强类型的客户端与服务端代码,支持同步/异步、单向串流、双向流。
优点
- 极低的序列化开销:protobuf 比 JSON 小 3-10 倍,解析速度更快。
- HTTP/2 多路复用:一个 TCP 连接可并发承载多个请求,避免了 HTTP/1.1 的队头阻塞。
- 原生流式机制:
stream关键字直接定义流式响应,无需 SSE 等变通方案。 - 强类型与自动生成代码:接口契约严格,减少字段错误,加速开发迭代。
- 拦截器与中间件:内置认证、日志、监控等拦截器机制,与云原生生态无缝衔接。
缺点
- Web 浏览器支持有限:无法直接从浏览器调用 gRPC 服务,需要 gRPC-Web 代理或 Envoy 转换。
- 可读性差:protobuf 编码为二进制,调试需要专用工具,不如 curl + JSON 直观。
- 学习曲线:需要理解 proto3 语法、流类型 (一元、服务端流、客户端流、双向流)。
- 负载均衡较复杂:长连接与多路复用使得传统 L4 负载均衡器失效,需要服务端连接池或 lookaside 负载均衡。
WebSocket:实时双向通信
WebSocket 是建立在 HTTP 升级基础上的全双工通信协议,允许客户端与服务端在一个长连接上持续交换消息。它在需要推送和低延迟交互的场景中表现优异。
在大模型中的应用
对于需要实时多轮交互的应用(如 AI 客服、实时协作),WebSocket 可以保持上下文,并由服务端主动推送消息。
连接建立后,消息帧可以是 JSON 或自定义格式:
{"type": "prompt", "content": "帮我写一段代码"}
{"type": "token", "token": "def"}
{"type": "token", "token": " hello"}
{"type": "end"}
你还可以双向发送控制信号,比如客户端可以取消生成、调整参数,服务端可发送心跳或状态变化。
优点
- 真正的全双工:无需依赖轮询,服务端可随时推送,延迟极低。
- 轻量级帧头:每个数据帧仅 2 字节开销,适合高频小数据包。
- Web 原生支持:所有现代浏览器均内置 WebSocket API,移动端库也很成熟。
- 会话保持自然:连接可绑定用户会话状态,避免每次重建上下文。
缺点
- 状态化服务扩展难:每个连接对应一个服务端实例,水平扩展时需要粘性会话 (sticky session)或消息总线同步。
- 重连与错误处理复杂:断线后需要客户端手动重连,并可能重放未完成的消息。
- 无内置请求-响应匹配:若同时发送多个请求,需要自定义消息 ID 来关联回复。
- 代理和防火墙限制:部分企业网络可能阻断 WebSocket 升级,需要 fallback 到轮询。
如何选择?场景化决策指南
每个协议都有其最佳实践场景,下表从多个维度进行对比:
| 维度 | RESTful | gRPC | WebSocket |
|---|---|---|---|
| 流式原生支持 | 通过 SSE 变通 | 原生支持 | 原生双向流 |
| 序列化格式 | JSON / 文本 | Protobuf (二进制) | 自定义 (常为 JSON) |
| 传输协议 | HTTP/1.1 (部分 HTTP/2) | HTTP/2 | WebSocket (ws/wss) |
| 浏览器兼容性 | 完美 | 需 gRPC-Web 转换 | 完美 |
| 强类型契约 | 无 (需 OpenAPI) | 内置 | 需自描述 |
| 连接开销 | 高 (每请求) | 中 (长连接 + 流) | 低 (单连接) |
| 调试便利性 | 极好 (curl) | 较差 (grpcurl) | 中等 (浏览器控制台) |
| 典型应用场景 | 简单问答、后台管理 | 高吞吐推理服务、微服务间通信 | AI 助手、实时对话、游戏 NPC |
决策树建议
- 如果服务主要面向浏览器端,且以一次性的问答为主 → 选择 RESTful,利用 SSE 实现流式。绝大部分 SaaS 化大模型 API(如 OpenAI, Anthropic)均采用此方案,生态最友好。
- 如果追求极致的吞吐和延迟,且客户端多为内部微服务或移动端 → 选择 gRPC。尤其适合自建推理集群,搭配 Envoy 作为 API 网关。
- 如果需要持久连接、双向实时交互,且服务状态复杂 → 选择 WebSocket。适合构建类似 ChatGPT 的长对话应用,需要服务端推送进度或客户端随时打断生成。
混合架构实践
成熟系统往往不会只使用一种协议。你可以设计一个协议适配层,内部统一使用 gRPC(低延迟、强类型)进行服务间通信,边缘网关同时暴露 RESTful 和 WebSocket 端点,根据来源自动转换。
- 外网 REST 端点 → 转为 gRPC 流式调用后端推理服务
- WebSocket 连接管理器 → 复用 gRPC 的双向流完成帧转发
- 浏览器 via gRPC-Web → 在网关侧将 HTTP/1.1 转为 HTTP/2 gRPC
这种分层架构兼顾了内外部的不同需求(如下图示意)。
[Browser] --REST/WS--> [API Gateway] --gRPC--> [LLM Engine]
[Internal Service] ---------gRPC-------------->
实战:用 FastAPI 实现 RESTful 流式端点
以下是一个基于 Python FastAPI 和 OpenAI SDK 的流式回答示例,展示如何通过 SSE 推送 token。
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import openai
import asyncio
app = FastAPI()
client = openai.AsyncOpenAI()
async def token_generator(prompt: str):
stream = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
stream=True
)
async for chunk in stream:
if chunk.choices[0].delta.content:
token = chunk.choices[0].delta.content
yield f"data: {token}\n\n"
await asyncio.sleep(0.01) # 模拟打字节奏
yield "data: [DONE]\n\n"
@app.post("/chat")
async def chat(prompt: str):
return StreamingResponse(token_generator(prompt), media_type="text/event-stream")
设计未来:新协议与趋势
- WebTransport:基于 QUIC,提供类似于 WebSocket 的双向流,但避免了队头阻塞,更适合不可靠网络上的实时流式传输。
- HTTP/3 + SSE:将流式构建在 QUIC 之上,降低连接建立延迟并改善多路复用。
- 模型服务标准化:社区正在推动类似 OpenAI API 的通用接口规范,未来可能通过 OpenAPI 或 protobuf 统一协议无关的语义。
在大模型 API 设计中,没有绝对的银弹。理解每种协议的核心价值与局限性,才能根据业务特性做到最优取舍。建议初期原型采用 RESTful 快速验证,待吞吐量和并发成为瓶颈时,逐步将内部调用替换为 gRPC,并视产品交互需求决定是否引入 WebSocket。这样既能保证开发效率,又能为性能优化留出空间。