gPRC

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

gRPC 客户端和服务器可以在各种环境中运行并相互通信,从 Google 内部的服务器到你自己的桌面,并且可以用 gRPC 支持的任何语言编写。因此,例如你可以轻松地用 Java 创建一个 gRPC 服务器,客户端使用 Go、Python 或Ruby。此外,最新的谷歌 API 将有 gRPC 版本的界面,让你可以轻松地将谷歌功能构建到应用程序中。

默认情况下,gRPC 使用 Protocol Buffers,这是 Google 用于序列化结构化数据的成熟开源机制(尽管它可以与 JSON 等其他数据格式一起使用)。

使用 Protocol Buffers 的第一步是在 proto 文件中定义需要序列化的数据结构。Protocol Buffers 数据被构造为消息(messages),其中每条消息是一个小的信息逻辑记录,其中包含一系列名值对(称为字段fields)。下面是一个简单的例子:

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

然后,一旦指定了数据结构,就可以使用 Protocol Buffers 编译器 protoc 从 proto 定义中以首选语言生成数据访问类。它们为每个字段提供了简单的访问器,如 name()set_name(),以及序列化/反序列化(serialize/parse)方法。因此,例如如果你选择的语言是C++,那么在上面的示例中运行编译器将生成一个名为 Person 的类。然后,你可以在应用程序中使用此类来填充、序列化和检索 Person 消息。

你可以在普通 proto 文件中定义 gRPC 服务,并将 RPC 方法参数和返回类型指定为消息

// The greeter service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

gRPC 使用 protoc 从 proto 文件生成代码,您可以获得生成的 gRPC 客户端和服务器代码,以及用于填充、序列化和检索消息类型的常规 Protocol Buffers 代码。

定义服务

gRPC 基于定义服务的思想,指定可以使用其参数和返回类型远程调用的方法。默认情况下,gRPC 使用 Protocol Buffers 作为接口定义语言(IDL=Interface Definition Language),用于描述服务接口和有效负载消息的结构。

service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

gRPC 允许用户定义 4 种服务

  1. Unary RPC rpc SayHello(HelloRequest) returns (HelloResponse);
  2. Server streaming RPC rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
  3. Client streaming RPC rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
  4. Bidirectional streaming RPC rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

Note: stream = sequence of messages

如何使用 API

gRPC提供 Protocol Buffers 编译器插件,用于生成客户端和服务器端代码。gRPC用户通常在客户端调用这些API,并在服务器端实现相应的API。

  • 在服务器端,服务器实现服务声明的方法,并运行 gRPC 服务器来处理客户端调用。gRPC 基础设施对传入的请求进行解码,执行服务方法,并对服务响应进行编码。
  • 在客户端,客户端有一个称为 stub 的本地对象(对于某些语言,首选术语是client),它实现了与服务相同的方法。然后,客户端可以在本地对象上调用这些方法,将调用的参数包装在适当的消息类型中,负责将请求发送到服务器并返回服务器的响应。

同步与异步

Ref: ROS Service vs ROS Action

Deadlines/Timeouts

gRPC 允许客户端指定他们愿意等待 RPC 完成多长时间,然后 RPC 被终止并出现 DEADLINE_EXCEEDED 错误。在服务器端,服务器可以查询特定 RPC 是否已超时,或者还有多少时间来完成 RPC。指定截止日期或超时是特定于语言的:一些语言API根据超时(持续时间)工作,而一些语言API根据截止日期(固定时间点)工作,可能有也可能没有默认截止日期。

RPC termination

在 gRPC 中,客户端和服务器都对调用的成功进行独立的本地确定,并且它们的结论可能不匹配。服务器也可以在客户端发送所有请求之前决定完成。

Cancelling an RPC

客户端或服务器可以随时取消 RPC。取消操作将立即终止 RPC,以便不再进行进一步的工作。

Metadata

元数据是有关特定 RPC 调用的信息(例如身份验证详细信息),其形式为键-值对列表,其中键是字符串,值通常是字符串,但可以是二进制数据。元数据对 gRPC 本身是不透明的,它允许客户端向服务器提供与调用相关的信息,反之亦然。元数据的访问取决于语言。

Channels

gRPC 通道提供到指定主机和端口上 gRPC 服务器的连接。它在创建客户端存根(stub)时使用。客户端可以指定通道参数来修改 gRPC 的默认行为,例如打开或关闭消息压缩。通道具有状态,包括已连接和空闲。

References

  1. gPRC
    1. What is gRPC?
  2. Protocol Buffers