vlambda博客
学习文章列表

grpc学习-简介和核心概念

简介

gRP将protocol buffers用作其接口定义语言(IDL)和其基础消息交换格式。在gRPC中,客户端应用程序可以直接在其他计算机上的服务器应用程序上调用方法,就好像它是本地对象一样,从而更轻松地创建分布式应用程序和服务。与许多RPC系统一样,gRPC围绕定义服务的思想,指定可通过其参数和返回类型远程调用的方法。在服务器端,服务器实现此接口并运行gRPC服务器以处理客户端调用。在客户端,客户端具有一个存根(在某些语言中仅称为客户端),提供与服务器相同的方法。

从Google内部的服务器到您自己的台式机,gRPC客户端和服务器都可以在各种环境中运行并相互通信,并且可以使用gRPC支持的任何语言编写。因此,例如,可以使用Go,Python或Ruby的客户端轻松地用Java创建gRPC服务器。此外,最新的Google API的接口将具有gRPC版本,可让轻松地在应用程序中内置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消息:

// The greeter service definition.service Greeter {// Sends a greetingrpc SayHello (HelloRequest) returns (HelloReply) {}}// The request message containing the user's name.message HelloRequest {string name = 1;}// The response message containing the greetingsmessage HelloReply {string message = 1;}

gRPC将protoc与特殊的gRPC插件一起使用,以从proto文件生成代码:您将生成生成的gRPC客户端和服务器代码,以及用于填充,序列化和检索消息类型的protocol buffer代码。

protocol buffer文档:

https://developers.google.com/protocol-buffers/docs/overview


使用API

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

1.在服务器端,服务器实现服务声明的方法,并运行gRPC服务器来处理客户端调用。gRPC基础结构解码传入的请求,执行服务方法,并对服务响应进行编码。

2.在客户端,客户端具有一个称为stub的本地对象(对于某些语言,首选术语是client),该对象实现与服务相同的方法。然后,客户端可以只在本地对象上调用这些方法,将调用的参数包装在适当的protocol buffer消息类型中-gRPC在将请求发送到服务器并返回服务器的protocol buffer响应之后进行查找。


同步与异步

阻塞的同步RPC调用直到服务器收到响应为止,是与RPC所追求的过程调用的抽象最接近的近似值。另一方面,网络本质上是异步的,并且在许多情况下能够启动RPC而不阻塞当前线程很有用。

大多数语言中的gRPC编程API都有同步和异步两种形式。


一元RPC

首先考虑最简单的RPC类型,其中客户端发送单个请求并返回单个响应。

1.客户端调用存根stub方法后,会通知服务器已使用该调用的客户端元数据,方法名称和指定的截止日期(如果适用)调用了RPC。

2.然后,服务器可以立即发送自己的初始元数据(必须在发送任何响应之前发送),也可以等待客户端的请求消息。哪个先发取决于特定于应用程序的。

3.服务器收到客户的请求消息后,它将完成创建和填充响应所必需的一切工作。然后将响应(如果成功)连同状态详细信息(状态代码和可选的状态消息)以及可选的尾随元数据一起返回(如果成功)给客户端。

4.如果响应状态为OK,则客户端将获得响应,从而在客户端完成呼叫。


服务器流式RPC

服务器流式RPC与一元RPC相似,不同之处在于服务器响应客户端的请求返回消息流。发送所有消息后,服务器的状态详细信息(状态代码和可选状态消息)和可选尾随元数据将发送到客户端。这样就完成了服务器端的处理。客户端收到所有服务器的消息后即完成操作。


双向流式RPC

在双向流式RPC中,调用由客户端调用方法启动,服务器接收客户端元数据,方法名称和期限。服务器可以选择发送回其初始元数据,也可以等待客户端开始流式传输消息。

客户端和服务器端流处理是特定于应用程序的。由于两个流是独立的,因此客户端和服务器可以按任何顺序读取和写入消息。例如,服务器可以等到接收到客户端的所有消息后再写消息,或者服务器和客户端可以打“ping-pong” –服务器收到请求,然后发回响应,然后客户端发送基于响应的另一个请求,依此类推。


截止时间/超时

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

指定期限或超时是特定于语言的:某些语言API按照超时(时间长短)工作,而某些语言API按照期限(固定时间点)工作,并且可能有也可能没有默认期限。


RPC终止

在gRPC中,客户端和服务器都对调用成功进行独立和本地确定,其结论可能不匹配。例如,这意味着一个在服务器端成功完成的RPC(“我已经发送了所有响应!”),而在客户端却失败了(“响应在我的截止日期之后到达!”)。服务器也有可能在客户端发送所有请求之前决定完成操作。


取消RPC

客户端或服务器都可以随时取消RPC。取消操作会立即终止RPC,因此无需进行进一步的工作。取消之前所做的更改不会回滚。


元数据

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


通道

gRPC通道提供到指定主机和端口上的gRPC服务器的连接。在创建客户端存根时使用。客户可以指定通道参数来修改gRPC的默认行为,例如打开或关闭消息压缩。通道具有状态,包括已连接和空闲。gRPC如何处理关闭通道取决于语言。某些语言还允许查询通道状态。