数据, 术→技巧

初步认识RPC框架gRPC

钱魏Way · · 3 次浏览

gRPC简介

gRPC 是一个现代化的、高性能的 远程过程调用(Remote Procedure Call, RPC)框架,由 Google 开发并开源。它基于 HTTP/2 协议,使用 Protocol Buffers(protobuf)作为接口定义语言(IDL)和数据序列化工具,是微服务通信和跨语言通信的理想选择。

核心概念

RPC(Remote Procedure Call)

gRPC 的核心是 RPC。它允许客户端像调用本地方法一样,调用远程服务器上的方法,而无需关心底层网络通信的细节。

Protocol Buffers

  • Protocol Buffers(protobuf) 是 Google 开发的一种轻量、高效的序列化数据格式。
  • gRPC 使用 protobuf 定义服务接口和消息格式,通过 .proto 文件生成客户端和服务端代码。

HTTP/2 支持

gRPC 构建在 HTTP/2 之上,具备以下特性:

  • 多路复用:单个 TCP 连接支持多个并发请求。
  • 双向流:支持客户端和服务端同时发送数据流。
  • 高效压缩:数据帧比 HTTP/1.x 更紧凑,减少带宽占用。
  • 低延迟:相比 HTTP/1.x,通信性能显著提升。

主要特性

  • 高效的数据传输
    • HTTP/2 协议:gRPC 使用 HTTP/2 作为传输协议,支持多路复用、头部压缩和流量控制,提高了网络传输的效率。
    • Protocol Buffers:默认使用 Protocol Buffers(protobuf)作为消息序列化格式,提供了高效的二进制编码,减少了数据传输的大小。
  • 多种编程语言支持
    • 多语言支持:gRPC 支持多种编程语言,包括但不限于:C++、Java、PythonGojsRubyC#Objective-CPHP
  • 双向通信
    • 单向调用:客户端发送请求,服务器返回响应。
    • 服务器流:服务器连续发送多个响应,客户端接收多个响应。
    • 客户端流:客户端连续发送多个请求,服务器接收多个请求后返回一个响应。
    • 双向流:客户端和服务器都可以连续发送多个请求和响应,实现全双工通信。
  • 服务定义
    • IDL(接口定义语言):使用 Protocol Buffers 的.proto 文件定义服务接口和消息类型。
    • 强类型:通过 protobuf 定义消息和服务接口,提供静态类型检查,避免序列化/反序列化错误。
    • 代码生成:根据.proto 文件自动生成客户端和服务器端的代码,简化开发过程。
  • 负载均衡和容错
    • 负载均衡:支持多种负载均衡策略,确保请求均匀分布到多个服务器实例。
    • 容错机制:支持重试、超时和断路器等容错机制,提高系统的可靠性和稳定性。
  • 认证和安全
    • TLS 支持:支持 TLS 加密,确保数据传输的安全性。
    • 认证机制:支持多种认证机制,如 OAuth2、JWT 等,确保请求的合法性。

通信模式

gRPC 提供以下四种通信模式,支持多种场景:

简单 RPC(Unary RPC)

  • 客户端发送单个请求,服务端返回单个响应。
  • 类似于函数调用。

rpc GetUser (GetUserRequest) returns (GetUserResponse);

服务器流式 RPC(Server-Streaming RPC)

  • 客户端发送请求,服务端返回多个响应(流式)。
  • 客户端可以接收响应流,直到服务器完成发送。

rpc ListUsers (ListUsersRequest) returns (stream User);

客户端流式 RPC(Client-Streaming RPC)

  • 客户端发送多个请求(流式),服务端接收并返回一个响应。

rpc UploadData (stream DataChunk) returns (UploadResponse);

双向流式 RPC(Bidirectional Streaming RPC)

客户端和服务端同时发送数据流,彼此独立,类似 WebSocket。

rpc Chat (stream ChatMessage) returns (stream ChatResponse);

gRPC 的优缺点

优点

  • 高性能:基于 HTTP/2 和 protobuf,延迟低、数据传输高效。
  • 跨语言支持:适合多语言团队和分布式系统。
  • 强类型:避免序列化/反序列化错误。
  • 流式通信:支持实时双向数据流。
  • 生态成熟:提供负载均衡、服务发现等工具。

缺点

  • 调试难度高:相比 REST,直接查看 protobuf 数据不如 JSON 直观。
  • 兼容性问题:与 HTTP/1.x 的兼容性较差,不适合浏览器直接访问。
  • 学习成本:需要学习 protobuf 和 gRPC 的使用方法。
  • 过度设计风险:对于小型项目,可能显得复杂和过重。

应用场景

  • 微服务通信
    • 服务间通信的高性能需求。
    • 复杂的多语言微服务体系。
  • 实时流式通信
    • 聊天系统、实时推送、视频流、物联网传感器数据等。
  • 跨语言 API
    • 开发跨语言 SDK,为外部系统提供高效的远程调用接口。
  • 大数据传输
    • 数据处理流水线中的高吞吐、低延迟传输。

gRPC与REST对比

gRPC 和 REST 是两种用于构建网络服务的通信协议,各自有其特点和适用场景。以下是对它们的对比:

特性 gRPC REST
协议基础 基于 HTTP/2,使用 Protocol Buffers 基于 HTTP/1.1,通常使用 JSON 或 XML
性能 高效,数据格式紧凑,支持流式通信 较慢,数据格式较大,基于请求-响应模式
易用性 需要学习 protobuf,适合多语言环境 简单易用,广泛支持,适合 Web 开发
功能特性 支持四种通信模式,内置负载均衡、重试、超时等 请求-响应模式,需手动处理负载均衡和重试等
适用场景 微服务通信、高性能场景、多语言支持 公开 Web API、简单 CRUD 操作、易于调试和测试

gRPC的使用

在 Python 中使用 gRPC 需要遵循以下步骤,涉及安装必要的库、定义服务接口、生成客户端和服务器代码、以及实现客户端和服务器。

安装 gRPC 和 Protocol Buffers

首先,你需要安装 grpcio 和 grpcio-tools,这两个库分别用于 gRPC 的运行时和 Protocol Buffers 编译器。

pip install grpcio grpcio-tools

定义服务接口

使用 Protocol Buffers(.proto 文件)定义服务接口和消息类型。例如,创建一个简单的 helloworld.proto 文件:

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

生成 Python 代码

使用 grpcio-tools 中的 protoc 编译器生成 Python 代码:

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto

这会生成 helloworld_pb2.py 和 helloworld_pb2_grpc.py,分别用于消息类和服务类。

实现服务器

创建一个 Python 文件来实现服务器逻辑:

from concurrent import futures
import grpc
import helloworld_pb2
import helloworld_pb2_grpc

class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()

实现客户端

创建一个 Python 文件来实现客户端逻辑:

import grpc
import helloworld_pb2
import helloworld_pb2_grpc

def run():
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='World'))
    print("Greeter client received: " + response.message)

if __name__ == '__main__':
    run()

运行服务和客户端

首先启动服务器:python server.py

然后在另一个终端窗口中启动客户端:python client.py

你应该会看到客户端收到的消息:“Greeter client received: Hello, World!”

以上步骤涵盖了使用 gRPC 和 Python 的基本流程。你可以根据需要扩展和修改服务定义和实现逻辑。

gRPC的测试

测试 gRPC 接口可以通过多种方法进行,具体选择取决于你的开发环境和工具链。以下是一些常用的 gRPC 接口测试方法:

使用 gRPCurl

grpcurl 是一个类似于 curl 的命令行工具,专门用于与 gRPC 服务器交互。它允许你调用 gRPC 服务的方法而无需编写代码。

安装: 你可以通过 go install 来安装 grpcurl。

go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest

使用: 你可以使用以下命令调用 gRPC 方法:

grpcurl -plaintext localhost:50051 YourService/YourMethod

这里 localhost:50051 是 gRPC 服务器地址,YourService/YourMethod 是要调用的服务和方法。

使用 Postman

Postman 是一个流行的 API 开发工具,最近也支持 gRPC 协议。

  • 创建 gRPC 请求: 在 Postman 中选择创建新的 gRPC 请求。
  • 配置请求: 输入 gRPC 服务器地址,选择要测试的方法,并提供必要的请求数据。
  • 发送请求: 发送请求并查看响应。

使用 BloomRPC

BloomRPC 是一个开源的 gRPC 客户端工具,提供图形界面来测试 gRPC 服务。

  • 下载和安装: 从 BloomRPC 的 GitHub 页面下载并安装应用。
  • 使用: 启动 BloomRPC,输入 gRPC 服务器地址,选择服务和方法,输入请求数据,然后发送请求查看响应。

使用自定义测试脚本

你可以编写测试脚本来调用 gRPC 接口。大多数编程语言都有 gRPC 客户端库,例如:

  • Python: 使用grpcio 和 grpcio-tools 库。
  • Go: 使用golang.org/grpc。
  • Java: 使用grpc。

编写测试脚本通常需要:

  • 编写客户端代码来加载.proto 文件生成的代码。
  • 设置与 gRPC 服务器的连接。
  • 调用服务方法并验证响应。

使用自动化测试框架

在大型项目中,你可能希望将 gRPC 接口测试集成到自动化测试框架中,如:

  • JUnit/TestNG(Java)
  • pytest(Python)
  • Go testing package(Go)

这些框架可以帮助你在持续集成/持续部署(CI/CD)过程中自动化 gRPC 接口的测试。

选择哪种方法取决于你的具体需求、项目规模以及团队的工具链偏好。对于简单的测试和调试,grpcurl 和 Postman 非常方便,而对于复杂的自动化测试,自定义脚本和自动化测试框架可能更合适。

参考链接:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注