gRPC简介

创建于 2024年3月22日修改于 2024年5月5日
gRPC

RPC


本篇为你介绍 gRPCProtocol Buffers。gRPC 既将 Protocol Buffers 用作其接口定义语言(IDL),又将其用作底层消息交换格式。

概览

在 gRPC 中,客户端应用可以直接调用不同机器上的服务器应用上的方法,就像调用本地对象一样。这使得开发者可以更容易地创建分布式应用程序和服务。 与许多 RPC 系统一样,gRPC 是围绕定义服务的概念构建的,指定可以远程调用的方法以及它们的参数和返回类型。 在服务器端,服务器实现此接口并运行一个gRPC服务器来处理客户端调用。在客户端,客户端有一个存根(stub,在某些语言中直接称为客户端),提供与服务器相同的方法。

gRPC

图片来自 https://grpc.io/

gRPC 客户端和服务器可以在各种环境中运行和相互通信 - 从 Google 内部的务器到你自己的桌面 - 并且可以用任何 gRPC 支持的语言编写。 例如,你可以轻松地在 Java 中创建一个 gRPC 服务器,并使用 Go、Python 或 Ruby 作为客户端。

使用 Protocol Buffers

默认情况下,gRPC 使用 Protocol Buffers。它是 Google 开源的一套非常成熟的序列化结构数据协议。

使用 Protocol Buffers 时的第一步是在 proto 文件中定义要序列化的数据的结构:这是一个带有 .proto 扩展名的普通文本文件。 Protocol Buffer 数据被结构化为消息(messages),其中每个消息都是一小条包含一系列名称-值对字段的逻辑记录。

这是一个简单的例子:

message Person {
  string name = 1;
  int32 id = 2;
  bool has_ponycopter = 3;
}

然后,一旦你指定了数据结构,你就可以使用 protocol buffer 编译器 protoc 根据你的 proto 定义生成你所选语言实现的数据访问类。 这些类为每个字段提供简单的访问器,例如 name()set_name(),以及用于将整个结构序列化成原始字节或从原始字节解析的方法。 例如,如果你选择的语言是 C++,则上面的示例交给编译器运行将生成一个名为 Person 的类。然后,你可以在应用程序中使用此类来填充、序列化和获取 Person 的 protocol buffer 消息。

你可以在 proto 文件中定义 gRPC 服务,其中 RPC 方法的参数和返回类型都通过 protocol buffer 消息指定:

// greeter 服务定义
service Greeter {
  // 发送问候语
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 包含用户姓名的请求消息
message HelloRequest {
  string name = 1;
}

// 包含问候语的响应消息
message HelloReply {
  string message = 1;
}

gRPC 使用带有特殊 gRPC 插件的 protoc 从你的 proto 文件生成代码:你将获得生成的 gRPC 客户端和服务端代码,以及用于填充、序列化和获取消息类型的常规 protocol buffer 代码。要了解有关 protocol buffer 的更多资料,包括如何在你使用的语言中安装带有 gRPC 插件的 protoc,请访问 protocol buffer 官网

Protocol buffer 版本

Protocol buffer 版本3(proto3)具有更简化的语法、一些新功能,以及支持更多语言。Proto3 目前在 Java、C++、Dart、Python、Objective-C、C#、轻量级运行时的 Android Java、Ruby 和 JavaScript 语言中可用。 这些版本均可从 protocol buffers GitHub仓库获得。 Go 语言可以使用来自 golang/protobuf官方包的生成器。更多语言的支持还在开发当中。你可以在 proto3 语言指南和每种语言的参考文档中找到更多信息。参考文档还包括 .proto 文件格式的正式规范

总之,虽然你可以继续使用 proto2(当前默认的 protocol buffer 版本)。但官方建议你在 gRPC 中使用 proto3,因为它可以让你使用更广泛的编程语言支持,同时可避免 proto2 客户端与 proto3 服务器(或者反过来)之间通信兼容性问题。