概述
在gRPC中,客户端应用可以像调用本地方法一样直接调用远程机器上服务端方法,帮助开发者更简单的创建分布式的应用和服务。和其他许多RPC系统一样,gRPC基于定义service的思想,指定一些带有参数和返回值的方法以供远程调用。服务端通过实现这些service接口在gRPC上处理客户端的请求。客户端拥有一个stub,它提供与服务器的方法相对应。
gRPC客户端和服务器可以在各种环境中运行并相互通信——并且可以用gRPC支持的任何语言编写,例如,您可以轻松地用Java创建gRPC服务器,用Go、Python或Ruby创建客户机。
注:下文中所有 RPC 代表 远程过程调用。
与 Protocol Buffers 的结合
默认情况下,gRPC使用Protocol Buffers作为数据传输层(由关于Protocol Buffers文章可以参阅我的另一个专栏Google Protocol Buffers),Protocol Buffers与gRPC结合时,使用protocol3语法,其语法更简洁、新的特性、支持更多的语言。
服务定义
gRPC使用protobuf作为接口定义语言(IDL),用于描述server interface和传递structure(结构体)。如果需要,也可以使用其他技术替代protobuf。
gRPC允许您定义四种服务方法:
- Unary(一元) RPCs,其中客户端向服务器发送单个请求并获得单个响应,就像普通的函数调用一样
rpc SayHello(HelloRequest) returns (HelloResponse);
- Server streaming RPCs,其中客户端向服务器发送请求并获得一个流来读取返回的消息序列,客户端从返回的流中读取message,直到没有message为止,gRPC保证在一个单独的RPC调用中message的有序性(message ordering)。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
- Client streaming RPCs,其中客户端重复使用提供的流,编写一系列消息并将它们发送到服务器,一旦客户端完成了消息的编写,就变为等待状态,等待服务器读取这一系列message并返回response,同时gRPC保证单个RPC调用中的消息排序。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
- Bidirectional(双向) streaming RPCs,其中双方使用“读写流”(read-write stream)发送一系列消息,这两个流是独立进行的,所以客户端和服务器可以按照自己喜欢的方式读写数据,例如,服务器可以在返回响应之前等待所有客户端消息接收完成,或者它可以轮流读取消息然后写入消息,或者其他一些读和写的组合。每个流中的消息顺序将会被保留。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
使用service接口
从.proto文件中的服务定义开始,gRPC提供了protocol buffers编译器插件,可以生成客户端和服务器端代码。gRPC用户通常在客户端调用这些API,并在服务器端实现相应的API。
- 在服务端一侧,实现service公开的方法,同时gRPC服务端在运行的时候负责处理客户端的调用,gRPC基础设施(基本能力)对传入的请求进行解码并执行相应的service方法,最后对返回结果编码,返回给客户端。
- 在客户端一侧,有一个本地对象,称为stub,它实现与服务相同的方法。客户端就可以通过这个本地的stub调用这些方法。为合适的protocol buffers message类型的请求包装参数,gRPC负责向服务端发送请求并返回服务端protocol buffers方式的响应。
同步与异步
这些一直阻塞到服务端返回response为止的同步型RPC调用,是非常近似与RPC所期望的过程调用的抽象(我也不知道怎么翻译啊,很难理解啊,Synchronous RPC calls that block until a response arrives from the server are the closest approximation to the abstraction of a procedure call that RPC aspires to.)。另一方面,网络请求本质上市异步的,能够在不阻塞当前线程的情况下启动RPC是非常有用的。
声明周期
除了刚才提到的四种服务方法外,还有如下几点:
Deadlines/Timeouts
一次RPC在被 DEADLINE_EXCEEDED
RPC的终止
在gRPC中,客户端和服务端都对调用的成功进行独立的本地判断,就是说客户端和服务端对请求或者调用的成功的判断结果可能不一样,服务器也可以在客户端发送所有请求之前决定是否完成。
取消RPC
客户端或服务端可以在任何时候取消RPC。取消操作会立即终止RPC,不会再做任何工作。
注意:取消之前所做的更改不会回滚。
Metadata
MetaData 是以键值对list的形式来标识特定 RPC 调用的信息,key是字符串,value通常情况下是字符串,也可以是二进制数据。MetaData 对于 gRPC 本身是不透明的,它允许客户端提供与服务器调用相关联的信息,反之亦然。
Channels
在创建客户端 stub 的时候,一个 gRPC Channel 可以为服务端在指定的地址和端口号上建立通道。客户端可以指定 Channel 的参数取修改 gRPC 默认的运行状况,例如打开或关闭 message 压缩。Channel 是有状态的,包括 connected(连接中)和 idle (空闲)。
gRPC如何处理关闭 Channel 的问题取决于使用的是哪种语言。一些语言还允许查询 Channel 状态。