grpc 概述
gRPC 可以将协议缓冲区用作其接口定义语言和底层消息交换格式。在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,使得创建分布式应用程序和服务更加容易。与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以远程调用的方法及其参数和返回类型。在服务端,服务端实现这个接口并运行一个 gRPC 服务器来处理客户端调用。在客户端,客户端有一个存根(在某些语言中仅称为客户端),它提供与服务器相同的方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cOlG5hrY-1651396101220)(.grpc_images/07ce4396.png)]
gRPC 客户端和服务器可以在各种环境中运行和相互通信,并且可以用任何 gRPC 支持的语言编写,如 C++、Go、Python 、Ruby 、Java等。此外,最新的 Google API 中提供了接口的 gRPC 版本,可以让开发者轻松地将 Google 功能构建到自己的应用程序中。
使用协议缓冲区
默认情况下,gRPC 使用协议缓冲区作为其数据结构序列化的格式。使用协议缓冲区的第一步是在 proto 数据原型定义:这是一个带有.proto扩展名的普通文本文件。协议缓冲区数据被构造为 message,其中每条消息都是一个小的信息逻辑记录,定义格式为:属性-类型-字段名-序号。proto 格式的数据结构定义好后,gRPC 使用protoc特殊的 gRPC 插件从您的 proto 文件生成 gRPC 客户端和服务器代码, 以及用于填充、序列化和检索消息类型的常规协议缓冲区代码。与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以远程调用的方法及其参数和返回类型。在 proto 文件中定义 gRPC 服务,将协议缓冲区定义的message 指定为 gRPC 方法参数和返回类型。
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}
RPC四种服务方法
-
双端一元式 RPC: 客户端向服务器发送单个请求并获得单个响应,就像正常的函数调用一样。 -
服务端流式 RPC: 其中客户端向服务器发送请求并获取流以读回一系列消息。客户端从返回的流中读取,直到没有更多消息为止。gRPC 保证单个 RPC 调用中的消息顺序。 -
客户端流式 RPC: 其中客户端写入一系列消息并将它们发送到服务器,再次使用提供的流。一旦客户端完成了消息的写入,它就会等待服务器读取它们并返回它的响应。gRPC 再次保证了单个 RPC 调用中的消息顺序。 -
双端双流式 RPC: 双方使用读写流发送一系列消息。这两个流独立运行,因此客户端和服务器可以按照他们的任何顺序读取和写入:例如,服务器可以在写入响应之前等待接收所有客户端消息,或者它可以交替读取消息然后写入消息,或其他一些读取和写入的组合。保留每个流中消息的顺序。
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
// A feature with an empty name is returned if there's no feature at the given
// position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
RPC 生命周期
-
双端一元式 RPC: 一旦客户端调用了一个存根方法,服务器就会被通知该 RPC 已被调用,其中包含该调用的客户端元数据 、方法名称和指定的截止时间。然后,服务器可以立即发回自己的初始元数据(必须在任何响应之前发送),或者等待客户端的请求消息。一旦服务器收到客户端的请求消息,它就会执行任何必要的工作来创建和填充响应。然后将响应连同状态详细信息(状态代码和可选状态消息)和可选尾随元数据一起返回给客户端。如果响应状态为 OK,则客户端得到响应,从而完成客户端的调用。 -
服务端流式 RPC: 服务器流式 RPC 类似于一元 RPC,除了服务器返回消息流以响应客户端的请求。发送所有消息后,服务器的状态详细信息(状态代码和可选状态消息)和可选尾随元数据将发送到客户端。这样就完成了服务器端的处理。客户端在拥有服务器的所有消息后完成。 -
客户端流式 RPC: 客户端流式 RPC 类似于一元 RPC,不同之处在于客户端向服务器发送消息流而不是单个消息。服务器响应一条消息(连同其状态详细信息和可选的尾随元数据),通常但不一定在它收到所有客户端的消息之后。 -
双端双流式 RPC: 在双向流式 RPC 中,调用由调用方法的客户端和接收客户端元数据、方法名称和截止日期的服务器发起。服务器可以选择发回其初始元数据或等待客户端开始流式传输消息。客户端和服务器端流处理是特定于应用程序的。由于这两个流是独立的,客户端和服务器可以以任意顺序读写消息。例如,服务器可以等到它收到客户端的所有消息后再写入它的消息,或者服务器和客户端可以玩“乒乓”——服务器收到请求,然后发回响应,然后客户端发送基于响应的另一个请求,依此类推。
调用过程
- API:协议缓冲区根据定义的proto文件会生成相应的API,gRPC 用户通常在客户端调用这些 API,并在服务器端实现相应的 API。
- 服务端:服务端实现服务声明的方法,并运行一个 gRPC 服务器来处理客户端调用。gRPC 基础架构解码传入请求、执行服务方法并编码服务响应。
- 客户端:客户端有一个称为存根的本地对象,它实现与服务相同的方法。然后客户端可以在本地对象上调用这些方法,将调用的参数包装在适当的协议缓冲区消息类型中,gRPC 会在将请求发送到服务器并返回服务器的协议缓冲区响应之后进行处理。
- 同步与异步:在服务器收到响应之前阻塞的同步 RPC 调用是最接近 RPC 所追求的过程调用抽象的近似值。另一方面,网络本质上是异步的,在许多情况下,能够在不阻塞当前线程的情况下启动 RPC 是很有用的。
- 超时:gRPC 允许客户端指定在 RPC 因错误而终止之前,他们愿意等待 RPC 完成多长时间DEADLINE_EXCEEDED。在服务器端,服务器可以查询特定的 RPC 是否已超时,或者还剩多少时间来完成 RPC。指定超时是特定于语言的。
- RPC 终止:在 gRPC 中,客户端和服务器都对调用是否成功做出独立的本地判断,并且它们的结论可能不匹配。当客户端收到服务端返回的响应已经超时时,服务端是成功的,客户端是失败的。
- 取消 RPC:客户端或服务器都可以随时取消 RPC。取消会立即终止 RPC,以便不再进行任何工作。
- 元数据:元数据是有关特定 RPC 调用的信息(例如身份验证详细信息),采用键值对列表的形式,其中键是字符串,值通常是字符串,但也可以是二进制数据。元数据对 gRPC 本身是不透明的——它允许客户端提供与服务器调用相关的信息,反之亦然。
- 通道:gRPC 通道提供与指定主机和端口上的 gRPC 服务器的连接。它在创建客户端存根时使用。客户端可以指定通道参数来修改 gRPC 的默认行为,例如打开或关闭消息压缩。通道具有状态,包括connected和idle。gRPC 如何处理关闭通道取决于语言,一些语言还允许查询通道状态。
使用场景
- 低延迟、高度可扩展的分布式系统。
- 开发与云服务器通信的移动客户端。
- 设计一个需要准确、高效和语言独立的新协议。
- 分层设计以实现扩展,例如。身份验证、负载平衡、日志记录和监控等
|