欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

gRPC之概念

程序员文章站 2024-03-14 14:12:52
...

本文档介绍了一些关键的gRPC概念,概述了gRPC的体系结构和RPC生命周期。

它假设您已阅读什么是gRPC 有关特定语言的详细信息,请参阅所选语言的快速入门,教程和参考文档(如果有)(完整的参考文档即将推出)。

概观

服务定义

与许多RPC系统一样,gRPC基于定义服务的思想,指定可以使用其参数和返回类型远程调用的方法。 默认情况下,gRPC使用protocol buffs作为接口定义语言(IDL)来描述服务接口和有效负载消息的结构。 如果需要,可以使用其他替代方案。

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

message HelloRequest{ 
  string greeting = 1; 
} 

message HelloResponse {
  string reply = 1; 
} 

gRPC允许您定义四种服务方法:

  • 一元RPC,客户端向服务器发送单个请求并返回单个响应,就像正常的函数调用一样。
 rpc SayHello(HelloRequest) returns (HelloResponse){ } 
  • 服务器流式RPC,客户端向服务器发送请求并获取流以读取消息序列。 客户端从返回的流中读取,直到没有更多消息。
 rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){ } 
  • 客户端流式RPC,客户端再次使用提供的流写入一系列消息并将其发送到服务器。 一旦客户端写完消息,它就等待服务器读取它们并返回它的响应。
 rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) { } 
  • 双向流式RPC,其中双方使用读写流发送一系列消息。 这两个流独立运行,因此客户端和服务器可以按照他们喜欢的顺序进行读写:例如,服务器可以在写入响应之前等待接收所有客户端消息,或者它可以交替读取消息然后写入消息,或其他一些读写组合。 保留每个流中的消息顺序。
 rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){ } 

我们将在下面的RPC生命周期部分中更详细地介绍不同类型的RPC。

使用API​​表面

从.proto文件中的服务定义开始,gRPC提供了生成客户端和服务器端代码的协议缓冲区编译器插件。 gRPC用户通常在客户端调用这些API,并在服务器端实现相应的API。

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

同步与异步

在响应从服务器到达之前阻塞的同步RPC调用最接近RPC所期望的过程调用的抽象。 另一方面,网络本质上是异步的,在许多情况下,能够在不阻塞当前线程的情况下启动RPC是有用的。

大多数语言的gRPC编程表面都有同步和异步两种版本。 您可以在每种语言的教程和参考文档中找到更多信息(完整的参考文档即将推出)。

RPC生命周期

现在让我们仔细看看当gRPC客户端调用gRPC服务器方法时会发生什么。 我们不会查看实现细节,您可以在我们特定语言的页面中找到有关这些内容的更多信息。

一元RPC

首先让我们看一下最简单的RPC类型,客户端发送单个请求并返回单个响应。

  • 客户端在存根/客户端对象上调用该方法后,将通知服务器已使用此调用的客户端元数据 ,方法名称和指定的截止时间如果适用)调用RPC。
  • 然后,服务器可以立即发送回自己的初始元数据(必须在任何响应之前发送),或者等待客户端的请求消息 - 首先发生的是特定于应用程序的消息。
  • 一旦服务器具有客户端的请求消息,它就会执行创建和填充其响应所需的任何工作。 然后将响应与状态详细信息(状态代码和可选状态消息)以及可选的尾随元数据一起返回(如果成功)到客户端。
  • 如果状态为OK,则客户端获取响应,从而完成客户端的调用。

服务器流RPC

服务器流RPC类似于我们的简单示例,除了服务器在获取客户端的请求消息后发回响应流。 在发回所有响应之后,服务器的状态详细信息(状态代码和可选状态消息)和可选的尾随元数据将被发送回服务器端完成。 一旦客户端拥有所有服务器的响应,客户端就会完成。

客户端流式RPC

客户端流式RPC也类似于我们的简单示例,除了客户端向服务器发送请求流而不是单个请求。 服务器发送回单个响应,通常但不一定在收到所有客户端请求后,以及其状态详细信息和可选的尾随元数据。

双向流式RPC

在双向流式RPC中,调用再次由调用方法的客户端和接收客户端元数据,方法名称和截止时间的服务器启动。 服务器再次可以选择发回其初始元数据或等待客户端开始发送请求。

接下来会发生什么取决于应用程序,因为客户端和服务器可以按任何顺序读写 - 流完全独立地运行。 因此,例如,服务器可以等到它在收到所有客户端的消息之后再写入其响应,或者服务器和客户端可以“乒乓”:服务器获取请求,然后发回响应,然后客户端发送另一个基于响应的请求,等等。

截止日期/超时

gRPC允许客户端指定在RPC以错误DEADLINE_EXCEEDED终止之前,他们愿意等待RPC完成的时间。 在服务器端,服务器可以查询特定RPC是否已超时,或者剩余多少时间来完成RPC。

指定截止日期或超时的方式因语言而异 - 例如,并非所有语言都有默认截止日期,某些语言API在截止日期(固定时间点)工作,某些语言API在超时方面工作(持续时间)。

RPC终止

在gRPC中,客户端和服务器都对呼叫的成功进行独立和本地的确定,并且它们的结论可能不匹配。 这意味着,例如,您可以在服务器端成功完成RPC(“我已经发送了所有响应!”),但在客户端失败(“我的截止日期后响应已到达!”)。 在客户端发送所有请求之前,服务器也可以决定完成。

取消RPC

客户端或服务器可以随时取消RPC。 取消立即终止RPC,以便不再进行进一步的工作。 它不是 “撤消”:取消之前所做的更改将不会被回滚。

元数据

元数据是关键字值对列表形式的特定RPC调用的信息,其中键是字符串,值通常是字符串(但可以是二进制数据)。 元数据对gRPC本身是不透明的 - 它允许客户端提供与服务器调用相关的信息,反之亦然。

对元数据的访问取决于语言。

通道

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

gRPC如何处理关闭渠道与语言有关。 某些语言也允许查询通道状态。

相关标签: gRPC