gRPC是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于Protobuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。在gRPC中一个客户端能够像使用本地对象那样直接调用位于不一样机器上的服务端应用的方法(methods)。这让你可以更容易的构建分布式的应用和服务。和其余RPC
系统相似,gRPC
也是基于定义一个服务,指定服务能够被远程调用的方法以及他们的参数和返回类型。在服务端,实现服务的接口而后运行一个gRPC
服务来处理可出端的请求。在客户端,客户端拥有一个存根(stub在某些语言中仅称为客户端),提供与服务器相同的方法。编程
·gRPC
客户端和服务器能够在各类环境中运行并相互通讯,而且可使用gRPC
支持的任何语言编写。所以,例如,您可使用Go,Python或Ruby的客户端轻松地用Java建立gRPC
服务器。此外,最新的Google API的接口将拥有gRPC
版本,可以让您轻松地在应用程序中内置Google功能。服务器
默认状况下,gRPC使用protocol buffer,用于序列化结构化数据(尽管它能够与其余数据格式(例如JSON)一块儿使用)。使用协议缓冲区的第一步是在proto文件中为要序列化的数据定义结构:proto文件扩展名为.proto的普通文本文件。protocol buffer数据被构造为消息,其中每一个消息都是信息的逻辑记录,其中包含一系列称为字段的名称/值对。这是一个简单的示例:网络
message Person { string name = 1; int32 id = 2; bool has_ponycopter = 3; }
定义了数据结构后,就可使用protocol buffer编译器protoc
生成你所选语言的数据访问类。访问类为每一个字段提供了简单的访问器(例如name()
)和set_name()
),以及将整个结构序列化为原始字节或从原始字节中解析出整个结构的方法-例如,若是您选择的语言是C ++,则在上面的示例将生成一个名为Person
的类。而后,您能够在应用程序中使用此类来填充,序列化和检索Person
的protocol buffer消息。数据结构
除此以外你还要在.proto
件中定义gRPC服务,并将RPC方法参数和返回类型指定为protocol buffer消息:框架
// 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插件。使用gRPC插件,你能够得到生成的gRPC客户端和服务器代码,以及用于填充,序列化和检索消息类型的常规protocol buffer访问类代码。异步
下面会更详细地介绍gRPC里的一些关键的概念。编程语言
与许多RPC系统同样,gRPC围绕定义服务的思想,指定可经过其参数和返回类型远程调用的方法。默认状况下,gRPC使用protocol buffer做为接口定义语言(IDL)来描述服务接口和有效负载消息的结构。若是须要,可使用其余替代方法。分布式
service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse); } message HelloRequest { string greeting = 1; } message HelloResponse { string reply = 1; }
gRPC容许定义四种服务方法:函数
rpc SayHello(HelloRequest) returns (HelloResponse){ }
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){ }
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) { }
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){ }
在下面的RPC生命周期章节咱们会更详细的比较这几种不一样的RPC。性能
从.proto
文件中的服务定义开始,gRPC提供了protocol buffer编译器插件,插件可生成客户端和服务器端代码。 gRPC用户一般在客户端调用这些API,并在服务器端实现相应的API。
同步RPC调用会阻塞当前线程直到服务器收到响应为止,这是最接近RPC所追求的过程调用抽象的近似方法。另外一方面,网络本质上是异步的,而且在许多状况下可以启动RPC而不阻塞当前线程颇有用。
大多数语言中的gRPC编程界面都有同步和异步两种形式。能够在每种语言的教程和参考文档中找到更多信息。
如今让咱们具体看一下当一个gRPC客户端调用了一个gRPC服务器的方法后都发生了什么。咱们不会查看具体实现细节,留到后面的编程语言教程中再看实现细节。
首先来看一个最简单的RPC类型,客户端发送一个请求而后接受一个响应。
一个服务器流式RPC与简单的一元RPC相似,不一样的是服务器在接收到客户端的请求消息后会发回一个响应流。在发送回全部的响应后,服务器的状态详情(状态码和可选的状态信息)和可选的尾随元数据会被发回以完成服务端的工做。客户端在接收到全部的服务器响应后即完成操做。
客户端流式RPC也相似于一元PRC,不一样之处在于客户端向服务器发送请求流而不是单个请求。服务器一般在收到客户端的全部请求后(但不必定)发送单个响应,以及其状态详细信息和可选的尾随元数据。
在双向流式RPC中,调用再次由客户端调用方法发起,服务器接收客户端元数据,方法名称和期限。一样,服务器能够选择发回其初始元数据,或等待客户端开始发送请求。
接下来发生的状况取决于应用程序,由于客户端和服务器能够按任何顺序进行读取和写入-流操做彻底是独立地运行。所以,例如,服务器能够等到收到全部客户端的消息后再写响应,或者服务器和客户端能够玩“乒乓”:服务器收到请求,而后发回响应,而后客户端发送基于响应的另外一个请求,依此类推。
gRPC容许客户端指定在RPC被DEADLINE_EXCEEDED
错误终结前愿意等待多长时间来让RPC完成工做。在服务器端,服务器能够查看一个特定的RPC是否超时或者还有多长时间剩余来完成RPC。
如何指按期限或超时的方式因语言而异-例如,并不是全部语言都有默认期限,某些语言API按照期限(固定的时间点)工做,而某些语言API根据超时来工做(持续时间)。
在gRPC中,客户端和服务端对调用是否成功作出独立的基于本地的决定,并且两端的结论有可能不匹配。这意味着,好比说,你可能会有一个在服务端成功完成(“我已经发送完全部响应了”)可是在客户端失败(“响应是在我指定的deadline以后到达的”)的RPC。服务器也有可能在客户端发送全部请求以前决定RPC完成了。
客户端或服务器均可以随时取消RPC。取消操做将当即终止RPC,所以再也不进行任何工做。这不是“撤消”:取消以前所作的更改不会回滚。
元数据是以键值对列表形式提供的关于特定RPC调用的信息(好比说身份验证详情),其中键是字符串,值一般来讲是字符串(可是也能够是二进制数据)。元数据对gRPC自己是不透明的-它容许客户端向服务器提供与调用相关的信息,反之亦然。
对元数据的访问取决于语言。
一个gRPC通道提供了一个到指定主机和端口号的gRPC服务器的链接,它在建立客户端存根(或者对某些语言来讲就是“客户端”)时被使用。客户端能够指定通道参数来更改gRPC的默认行为,好比说打开/关闭消息压缩。每一个通道都有状态,状态包括connected
和idle
(闲置)
gRPC怎么处理关掉的通道是语言相关的,有些语言还容许查询通道的状态。