前言

gRPC 的名称来源于 "Google Remote Procedure Call",最初由 Google 在 2015 年开源,现已成为云原生计算基金会(CNCF)的孵化项目,被广泛应用于 Kubernetes、Envoy 等知名项目中。

gRPC 接口简介

gRPC 是一种高性能、开源的远程过程调用(RPC)框架,由 Google 开发,旨在简化分布式系统中服务之间的通信。它基于 HTTP/2 协议,并使用 Protocol Buffers 作为接口定义语言(IDL)和消息序列化格式,提供了高效、强类型、跨语言的通信能力。

一、核心概念与工作原理

1-1、什么是 RPC

RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,允许程序调用位于另一台计算机上的子程序,而无需显式处理底层网络通信细节。对于开发者而言,调用远程服务就像调用本地函数一样简单。

1-2、gRPC 的工作流程

gRPC 允许客户端像调用本地方法一样调用远程服务。服务通过 .proto 文件定义,其中包含服务接口、方法、参数和返回类型。通过 gRPC 的工具链,可以自动生成客户端存根(stub)和服务器骨架(skeleton)代码。

通信过程包括以下步骤:

  1. 客户端调用:客户端调用本地存根方法,就像调用普通函数一样
  2. 序列化:请求数据被序列化为 Protocol Buffers 二进制格式
  3. 传输:数据通过 HTTP/2 传输到服务器
  4. 服务端处理:服务器反序列化数据,调用对应的服务逻辑
  5. 响应返回:服务器返回序列化后的响应数据,客户端接收并反序列化

如下图所示:(今天的图是中英文双语版本,花钱了都得贴上来!)
在这里插入图片描述
在这里插入图片描述

二、gRPC 的主要特性

2-1、高性能

  • 基于 HTTP/2 协议,支持多路复用、头部压缩和服务器推送
  • 单一 TCP 连接上可并发处理多个请求/响应,显著降低延迟
  • 二进制分帧层提供更高效的数据传输

2-2、Protocol Buffers

  • Google 开发的结构化数据序列化格式
  • 比 JSON 或 XML 更紧凑(通常小 3-10 倍),解析速度更快(快 20-100 倍)
  • 强类型定义,编译时即可发现类型错误
  • 支持向后和向前兼容的演化

2-3、强类型与代码生成

  • 通过 .proto 文件定义服务契约
  • 自动生成客户端和服务端代码(支持 10+ 种语言)
  • 编译时类型检查,减少运行时错误

2-4、流式通信模式

gRPC 支持四种通信模式,满足不同场景需求:

模式 描述 适用场景
Unary RPC 客户端发送单个请求,服务端返回单个响应 简单的请求-响应场景
Server Streaming 客户端发送单个请求,服务端返回多个响应 数据推送、实时通知
Client Streaming 客户端发送多个请求,服务端返回单个响应 文件上传、批量处理
Bidirectional Streaming 客户端和服务端都可以独立发送多个消息 实时聊天、在线游戏

2-5、自动代码生成

  • 使用 protoc 编译器自动生成代码
  • 简化开发流程,减少手动编码工作量
  • 保持多语言之间接口的一致性

三、gRPC 的优势与适用场景

gRPC 在性能、类型安全和多语言支持方面具有显著优势,特别适用于以下场景:

3-1、微服务架构

  • 服务间高效通信:低延迟、高吞吐量的内部服务调用
  • 服务发现集成:与 Consul、etcd、Kubernetes 等服务发现工具无缝集成
  • 负载均衡:支持客户端和服务端负载均衡

3-2、移动客户端与浏览器

  • 低延迟:更小的数据包体积,更快的序列化速度
  • 低带宽消耗:二进制格式比 JSON 更紧凑
  • gRPC-Web:支持浏览器客户端通过 HTTP/1.1 调用 gRPC 服务

3-3、实时应用

  • 在线游戏:低延迟的双向流通信
  • 实时数据分析:持续的数据流推送
  • IoT 设备通信:高效的资源利用,适合受限设备

3-4、跨语言系统

  • 多语言团队协作:不同技术栈的服务可以无缝集成
  • 遗留系统现代化:逐步迁移,保持接口兼容

GRPC的优势与适用场景如下所示:
在这里插入图片描述

四、gRPC vs REST 详细对比

特性 gRPC REST
协议 HTTP/2 HTTP/1.1 或 HTTP/2
数据格式 Protocol Buffers(二进制) JSON/XML(文本)
性能 高(二进制,体积小,解析快) 中(文本格式,体积大)
流式支持 原生支持四种流模式 需额外实现(如 WebSocket)
类型安全 强类型,编译时检查 弱类型,运行时检查
代码生成 自动生成客户端/服务端代码 需手动编写或使用第三方工具
浏览器支持 需 gRPC-Web 代理 原生支持
调试难度 较难(二进制格式) 简单(人类可读)
缓存 需额外配置 HTTP 缓存机制成熟

4-1、选择建议

使用 gRPC 的场景:

  • 内部微服务通信
  • 需要高性能、低延迟的场景
  • 多语言环境下的服务集成
  • 实时流数据处理

使用 REST 的场景:

  • 对外公开的 API
  • 需要浏览器直接访问的场景
  • 需要利用 HTTP 缓存机制
  • 调试和测试便利性优先

五、示例:定义与实现

5-0、架构图&依赖安装

整体架构图:

┌─────────────────────────────────────────────────────────────────┐
│                         gRPC 工作流程                            │
└─────────────────────────────────────────────────────────────────┘

  ┌─────────────┐                      ┌─────────────┐
  │   客户端     │  ◄────────────────►  │   服务端     │
  │  (client.py) │     HTTP/2 网络       │ (service.py) │
  └──────┬──────┘                      └──────┬──────┘
         │                                    │
         │  1. 调用存根方法                      │
         │     stub.SayHello(request)           │
         │                                    │
         │  2. 序列化 (Protobuf)                 │
         │     HelloRequest → 二进制数据         │
         │                                    │
         │  3. HTTP/2 传输                     │
         │     发送二进制数据 ─────────────────►│
         │                                    │
         │                              4. 反序列化
         │                              二进制 → HelloRequest
         │                                    │
         │                              5. 执行业务逻辑
         │                              GreeterService.SayHello()
         │                                    │
         │                              6. 序列化响应
         │                              HelloReply → 二进制
         │                                    │
         │  7. 反序列化响应 ◄─────────────────│
         │     二进制 → HelloReply              │
         │                                    │
         │  8. 返回结果                        │
         │     response.message               │

依赖安装:

pip install grpcio grpcio-tools

我的代码文件目录如下所示:

D:\pycharmProject\jf_inner_skills\Local\Experiment\GRPC\
├── client.py       # 客户端代码
├── grpc.md         # 文档
├── grpc.proto      # proto 文件
└── service.py      # 服务端代码

5-1、定义服务(grpc.proto 文件)

以下是一个简单的 gRPC 服务定义示例:这相当于约定接口,客户端和服务端都同意 “有一个叫 SayHello 的方法,接收 HelloRequest,返回 HelloReply”。

syntax = "proto3";

package example;

// 定义服务
service Greeter {
  // 一元 RPC
  rpc SayHello (HelloRequest) returns (HelloReply);
  
  // 服务端流式 RPC
  rpc SayHelloStream (HelloRequest) returns (stream HelloReply);
}

// 请求消息
message HelloRequest {
  string name = 1;
  int32 age = 2;
  repeated string hobbies = 3;  // 重复字段(数组)
}

// 响应消息
message HelloReply {
  string message = 1;
  int64 timestamp = 2;
}

生成python代码:

cd D:\pycharmProject\jf_inner_skills\Local\Experiment\GRPC

python -m grpc_tools.protoc --proto_path=. --python_out=. --grpc_python_out=. grpc.proto

执行后会生成:

  • grpc_pb2.py
  • grpc_pb2_grpc.py

这会根据 proto 文件自动生成:

  • grpc_pb2.py - 消息类(HelloRequest, HelloReply)
  • grpc_pb2_grpc.py - 服务类(GreeterServicer, GreeterStub)

为什么需要生成?

  • 把 proto 定义转换成 Python 代码
  • 包含序列化/反序列化的逻辑
  • 包含网络通信的底层代码

5-2、服务端实现(Python service.py)

通过 protoc 工具生成代码后,开发者可以实现服务端逻辑:

  • 创建一个 gRPC 服务器,监听 50051 端口
  • 注册 GreeterService 实现类
  • 等待客户端请求
  • 收到请求后,自动反序列化,调用 SayHello 方法
  • 把返回值序列化,发回客户端
from concurrent import futures
import grpc
import time
# 这里导入的是刚才生成的两个文件
import grpc_pb2
import grpc_pb2_grpc


class GreeterService(grpc_pb2_grpc.GreeterServicer):
    """实现 Greeter 服务"""

    def SayHello(self, request, context):
        """处理一元 RPC 请求"""
        # 获取请求参数
        name = request.name
        age = request.age
        hobbies = request.hobbies

        # 构建响应
        message = f"Hello, {name}! You are {age} years old."
        if hobbies:
            message += f" Your hobbies: {', '.join(hobbies)}"

        return grpc_pb2.HelloReply(
            message=message,
            timestamp=int(time.time())
        )

    def SayHelloStream(self, request, context):
        """处理服务端流式 RPC 请求"""
        name = request.name
        for i in range(5):
            yield grpc_pb2.HelloReply(
                message=f"Hello {name}, message {i + 1}",
                timestamp=int(time.time())
            )
            time.sleep(1)


def serve():
    """启动 gRPC 服务器"""
    # 创建线程池,最大 10 个工作线程
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

    # 注册服务
    grpc_pb2_grpc.add_GreeterServicer_to_server(GreeterService(), server)

    # 绑定端口
    server.add_insecure_port('[::]:50051')

    # 启动服务
    server.start()
    print("gRPC server started on port 50051")

    # 等待终止
    server.wait_for_termination()


if __name__ == '__main__':
    serve()

5-3、客户端实现(Python client.py)

客户端可以通过生成的存根调用服务:

  • 建立到服务端的连接(channel)
  • 创建存根(Stub) - 相当于远程服务的本地代理
  • 调用 stub.SayHello(),就像调用本地函数一样
  • gRPC 自动完成:序列化请求 → 发送 → 等待响应 → 反序列化响应
  • 返回 response 对象
import grpc
import greeter_pb2
import greeter_pb2_grpc


def run_unary():
    """一元 RPC 调用示例"""
    # 创建不安全的通道
    channel = grpc.insecure_channel('localhost:50051')
    
    # 创建客户端存根
    stub = greeter_pb2_grpc.GreeterStub(channel)
    
    # 构建请求
    request = greeter_pb2.HelloRequest(
        name="World",
        age=25,
        hobbies=["coding", "reading"]
    )
    
    # 调用远程方法
    try:
        response = stub.SayHello(request)
        print(f"Received: {response.message}")
        print(f"Timestamp: {response.timestamp}")
    except grpc.RpcError as e:
        print(f"RPC failed: {e.code()}: {e.details()}")


def run_streaming():
    """流式 RPC 调用示例"""
    channel = grpc.insecure_channel('localhost:50051')
    stub = greeter_pb2_grpc.GreeterStub(channel)
    
    request = greeter_pb2.HelloRequest(name="StreamUser")
    
    # 处理流式响应
    responses = stub.SayHelloStream(request)
    for response in responses:
        print(f"Stream received: {response.message}")


if __name__ == '__main__':
    run_unary()
    # run_streaming()

启动服务器端以及客户端:

cd D:\pycharmProject\jf_inner_skills\Local\Experiment\GRPC
python service.py
python client.py

启动后如下图所示:
在这里插入图片描述
在这里插入图片描述

5-4、核心概念解释

在这里插入图片描述

5-5、流程总结

写 proto 文件 ──► 生成代码 ──► 服务端实现业务逻辑 ──► 客户端调用存根
    │                │                │                    │
    ▼                ▼                ▼                    ▼
定义接口          自动生成          启动服务等待请求       像调本地函数一样
服务和消息        序列化代码         自动反序列化/序列化     自动完成网络通信

六、高级特性

6-1、拦截器(Interceptors)

拦截器允许在请求处理前后执行自定义逻辑,如日志记录、认证、监控等:

class LoggingInterceptor(grpc.ServerInterceptor):
    def intercept_service(self, continuation, handler_call_details):
        print(f"Received call: {handler_call_details.method}")
        return continuation(handler_call_details)

6-2、元数据(Metadata)

通过元数据传递额外的上下文信息,如认证令牌、请求 ID 等:

# 客户端发送元数据
metadata = [('authorization', 'Bearer token123')]
response = stub.SayHello(request, metadata=metadata)

# 服务端读取元数据
metadata = dict(context.invocation_metadata())
token = metadata.get('authorization', '')

6-3、截止时间(Deadline)

设置请求超时时间,防止长时间等待:

# 设置 5 秒超时
try:
    response = stub.SayHello(request, timeout=5)
except grpc.RpcError as e:
    if e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
        print("Request timed out")

6-4、错误处理

gRPC 使用状态码表示错误类型:

状态码 描述
OK 成功
CANCELLED 操作被取消
UNKNOWN 未知错误
INVALID_ARGUMENT 参数无效
DEADLINE_EXCEEDED 超时
NOT_FOUND 资源未找到
ALREADY_EXISTS 资源已存在
PERMISSION_DENIED 权限不足
UNAUTHENTICATED 未认证
UNAVAILABLE 服务不可用

七、注意事项与最佳实践

7-1、版本兼容性

  • Protocol Buffers 提供良好的前后向兼容性
  • 字段编号一旦分配不可更改,只能废弃
  • 字段类型更改需谨慎,可能导致兼容性问题
  • 新增字段使用 optional 或设置默认值

7-2、安全性

  • TLS/SSL:生产环境必须使用加密传输
    credentials = grpc.ssl_channel_credentials()
    channel = grpc.secure_channel('server.com:50051', credentials)
    
  • 认证机制:支持 OAuth2、JWT、自定义令牌等
  • 拦截器认证:在拦截器中统一处理认证逻辑

7-3、性能优化

  • 连接池:复用 gRPC 通道,避免频繁创建
  • 流控:合理设置窗口大小和缓冲区
  • 压缩:启用消息压缩减少传输体积
    channel = grpc.insecure_channel(
        'localhost:50051',
        options=[('grpc.default_compression_algorithm', 2)]
    )
    

7-4、调试工具

  • grpcurl:命令行工具,类似 curl,用于测试 gRPC 服务
    grpcurl -plaintext localhost:50051 list
    grpcurl -plaintext -d '{"name":"World"}' localhost:50051 example.Greeter/SayHello
    
  • BloomRPC:图形化 gRPC 客户端工具
  • Wireshark:支持 HTTP/2 和 protobuf 解析
  • gRPC 反射:启用反射服务供调试工具发现服务定义

7-5、生产环境建议

  • 使用服务网格(如 Istio、Linkerd)管理服务间通信
  • 实现健康检查和优雅关闭
  • 配置适当的超时和重试策略
  • 监控关键指标:延迟、错误率、吞吐量

八、总结

gRPC 是现代分布式系统中高效、可靠的通信解决方案,特别适合:

  • 高性能要求的微服务架构
  • 多语言环境下的服务集成
  • 实时数据流处理场景
  • 移动和 IoT 设备通信

通过 Protocol Buffers 提供的强类型契约、HTTP/2 的高性能传输,以及丰富的流式通信模式,gRPC 已成为云原生时代服务间通信的首选方案之一。


总结

还得是Nanobanana。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐