EN

gRPC AI 服务:完整集成指南

使用 gRPC 协议缓冲区的高性能 AI 服务

返回教程列表
进阶10 分钟

gRPC AI 服务:完整集成指南

使用 gRPC 协议缓冲区的高性能 AI 服务

gRPC 构建 AI 服务集成指南(2026):适合内部服务间推理流量——proto 契约、server streaming 流 token、deadline 传播取消上游生成。含完整 proto/Python 异步代码、负载均衡坑、与 REST+SSE 的诚实对比。

gRPC for AI Services: Integration Guide

gRPC 在 AI 技术栈中真正发光发热的场景只有一个:基础设施内部的服务间推理流量——推荐服务每分钟调用模型服务器上万次,ML 微服务流水线互相传递张量。对于面向浏览器的 AI 聊天,普通的 HTTP + SSE 仍然是正确选择(浏览器无法原生使用 gRPC)。本指南将构建一个流式 LLM 推理服务的 gRPC 实现,并诚实地分析其优势所在。

为什么内部 AI 流量选择 gRPC

  • Server streaming 是一等公民——token 流直接映射到 stream 响应,无需 SSE 框架的 hack。
  • Protobuf 契约——请求/响应结构在接触服务的每种语言中都会经过编译器检查;没有 JSON 漂移。
  • HTTP/2 多路复用 + 二进制编码——当调用小而频繁时,开销明显低于 JSON-over-HTTP/1.1(每次调用节省毫秒级时间;在数千 QPS 时才有意义,10 QPS 时无所谓)。
  • 内置截止时间——timeout 会在调用链中传播,这正是包装可能挂起的模型时所需要的。
  • 契约

    protobuf
    // llm.proto
    syntax = "proto3";
    package llm.v1;

    service LLMService { // Unary — 分类、嵌入、短补全 rpc Complete(CompleteRequest) returns (CompleteResponse); // Server streaming — 逐 token 生成 rpc CompleteStream(CompleteRequest) returns (stream TokenChunk); }

    message CompleteRequest { string model = 1; repeated Message messages = 2; int32 max_tokens = 3; } message Message { string role = 1; // "user" | "assistant" | "system" string content = 2; } message CompleteResponse { string text = 1; Usage usage = 2; } message TokenChunk { string token = 1; bool done = 2; Usage usage = 3; // 在最后一个 chunk 中填充 } message Usage { int32 input_tokens = 1; int32 output_tokens = 2; }

    使用 python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. llm.proto 生成桩代码。

    服务端——包装真实后端

    一种常见的生产形态:gRPC 服务是 vLLM、Ollama 或云提供商之上的门面,添加了认证、日志和路由。异步实现:

    python
    import grpc.aio
    from openai import AsyncOpenAI
    import llm_pb2, llm_pb2_grpc

    upstream = AsyncOpenAI(base_url='http://vllm:8000/v1', api_key='-') # vLLM 的 OpenAI 兼容端点

    class LLMService(llm_pb2_grpc.LLMServiceServicer): async def CompleteStream(self, request, context): stream = await upstream.chat.completions.create( model=request.model, messages=[{'role': m.role, 'content': m.content} for m in request.messages], max_tokens=request.max_tokens or 1024, stream=True, ) async for chunk in stream: token = chunk.choices[0].delta.content or '' if token: yield llm_pb2.TokenChunk(token=token, done=False) yield llm_pb2.TokenChunk(token='', done=True)

    async def serve(): server = grpc.aio.server() llm_pb2_grpc.add_LLMServiceServicer_to_server(LLMService(), server) server.add_insecure_port('[::]:50051') # 生产环境使用 mTLS await server.start() await server.wait_for_termination()

    (模型本身的部署是另一个话题——参见 vLLM 和 TensorRT-LLM 推理优化。)

    客户端——截止时间是关键

    python
    async with grpc.aio.insecure_channel('llm-service:50051') as channel:
        stub = llm_pb2_grpc.LLMServiceStub(channel)
        call = stub.CompleteStream(
            llm_pb2.CompleteRequest(
                model='qwen2.5-coder:32b',
                messages=[llm_pb2.Message(role='user', content='解释 HTTP/2 多路复用')],
            ),
            timeout=60.0,   # 硬截止时间——作为 gRPC deadline 传播到服务端
        )
        async for chunk in call:
            print(chunk.token, end='', flush=True)
    

    如果截止时间在生成过程中到期,客户端会收到 DEADLINE_EXCEEDED,而且——关键的是——服务端会看到取消信号,从而可以停止(昂贵的)上游生成。在长时间的服务端循环中检查 context.cancelled() 并取消上游调用;否则你会为无人接收的 token 持续付费。

    生产注意事项

  • 负载均衡:gRPC 的长期 HTTP/2 连接会击败简单的 L4 均衡器——所有流量都粘在一个后端上。使用 L7 代理(Envoy、Linkerd)或客户端负载均衡。
  • 浏览器:需要 grpc-web + 代理。此时,对于聊天 UI,SSE 的机制更少——参见 SSE 流式指南;关于通用传输决策,参见 流式 vs 轮询
  • 消息大小:默认最大值为 4MB——如果传递嵌入或图像,请提高 max_receive_message_length
  • 重试:确保一元端点幂等,并在服务配置中配置重试策略,而不是在调用方临时处理。
  • gRPC vs REST+SSE for AI,诚实地

    gRPCREST + SSE

    内部服务间通信✅ 最佳选择可行 浏览器客户端⚠️ grpc-web + 代理✅ 原生支持 契约强制✅ protobufOpenAPI(实践中较弱) 流式✅ 原生,双向仅服务端→客户端 可调试性grpcurl, reflectioncurl — 所有工具 团队熟悉度较低普遍

    如果你尚未运行 gRPC 基础设施,仅凭一个 LLM 门面很少值得引入它。如果你已经在用,流式 + 截止时间语义比 REST 更适合。

    FAQ

    双向流——何时使用? 实时对话轮次(语音代理、交互式会话)。大多数请求/响应 LLM 流量只需要 server streaming。

    错误如何映射? 使用规范状态码:INVALID_ARGUMENT 用于不良提示,RESOURCE_EXHAUSTED 用于速率限制(客户端将其视为可退避重试),UNAVAILABLE 用于上游故障。


    *最后更新:2026 年 6 月。*

    相关工具

    grpcpython
    所属主题:API 与集成开发