探秘gRPC——gRPC原理详解
RPC 即远程过程调用协议(Remote Procedure Call Protocol),可以让我们像调用本地对象一样发起 远程调用。RPC 凭借其强大的治理功能,成为解决分布式系统通信问题的一大利器。
gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用 PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2+PB 保证了的高性能。
gRPC特性
1. gRPC基于服务的思想:定义一个服务,描述这个服务的方法以及入参出参,服务器端有这个服务 的具体实现,客户端保有一个存根,提供与服务端相同的服务
2. gRPC默认采用protocol buffer作为IDL(Interface Description Lanage)接口描述语言,服务之间通信 的数据序列化和反序列化也是基于protocol buffer的,因为protocol buffer的特殊性,所以gRPC 框架是跨语言的通信框架(与编程语言无关性),也就是说用Java开发的基于gRPC的服务,可以用 GoLang编程语言调用
3. gRPC同时支持同步调用和异步调用,同步RPC调用时会一直阻塞直到服务端处理完成返回结果, 异步RPC是客户端调用服务端时不等待服务段处理完成返回,而是服务端处理完成后主动回调客户 端告诉客户端处理完成
4. gRPC是基于http2协议实现的,http2协议提供了很多新的特性,并且在性能上也比http1提搞了许 多,所以gRPC的性能是非常好的
5. gRPC并没有直接实现负载均衡和服务发现的功能,但是已经提供了自己的设计思路。已经为命名 解析和负载均衡提供了接口
gRPC场景
低延迟,高度可扩展的分布式系统 开发与云服务器通信的客户端 设计一个准确,高效,且与语言无关的新协议时 分层设计,以实现扩展,例如。身份验证,负载平衡,日志记录和监控等。
数据封装和数据传输
早期的RPCJSON的方式,目前的RPC基本上都采用类似Protobuf的二进制序列化方式。 其差别在于:json的设计是给人看的,protobuf则是利于机器。
JSON
优点:在body中用JSON对内容进行编码,极易跨语言,不需要约定特定的复杂编码格式和Stub文件。 在版本兼容性上非常友好,扩展也很容易。
缺点:JSON难以表达复杂的参数类型,如结构体等;数据冗余和低压缩率使得传输性能差。
Protobuf
gRPC对此的解决方案是丢弃json、xml这种传统策略,使用 Protocol Buffer,是Google开发的一种跨 语言、跨平台、可扩展的用于序列化数据协议。
// XXXX.proto// rpc服务的类 service关键字, Test服务类名
service Test {// rpc 关键字,rpc的接口
rpc HowRpcDefine (Request) returns (Response) ; // 定义一个RPC方法
}// message 类,c++ classmessage Request {//类型 | 字段名字| 标号
int64 user_id = 1;string name = 2;}message Response {repeated int64 ids = 1; // repeated 表示数组
Value info = 2;
// 可嵌套对象
map<int, Value> values = 3; // 可输出map映射
}message Value {bool is_man = 1;int age = 2;}
以上是一个使用样例,包含方法定义、入参、出参。可以看出有几个明确的特点:
有明确的类型,支持的类型有多种
每个field会有名字
每个field有一个数字标号,一般按顺序排列(下文编解码会用到这个点)
能表达数组、map映射等类型
通过嵌套message可以表达复杂的对象
方法、参数的定义落到一个.proto 文件中,依赖双方需要同时持有这个文件,并依此进行编解码
网络传输效率问题
grpc采用HTTP2.0,相对于HTTP1.0 在 更快的传输和 更低的成本两个目标上做了改进。有以下几个基本 点:
HTTP2 未改变HTTP的语义(如GET/POST等),只是在传输上做了优化
引入帧、流的概念,在TCP连接中,可以区分出多个request/response
一个域名只会有一个TCP连接,借助帧、流可以实现多路复用,降低资源消耗
引入二进制编码,降低header带来的空间占用
HTTP1.1核心问题在于:在同一个TCP连接中,没办法区分response是属于哪个请求,一旦多个请求返 回的文本内容混在一起,则没法区分数据归属于哪个请求,所以请求只能一个个串行排队发送。这直接 导致了TCP资源的闲置。
HTTP2为了解决这个问题,提出了流的概念,每一次请求对应一个流,有一个唯一ID,用来区分不同的 请求。基于流的概念,进一步提出了帧,一个请求的数据会被分成多个帧,方便进行数据分割传输,每 个帧都唯一属于某一个流ID,将帧按照流ID进行分组,即可分离出不同的请求。这样同一个TCP连接中 就可以同时并发多个请求,不同请求的帧数据可穿插在一起,根据流ID分组即可。HTTP2.0基于这种二 进制协议的乱序模式 (Duplexing),直接解决了HTTP1.1的核心痛点,通过这种复用TCP连接的方式,不 用再同时建多个连接,提升了TCP的利用效率。
GRPC 4种模式
一元RPC模式
一元 RPC 模式也被称为简单 RPC 模式。在该模式中,当客户端调用服务器端的远程方法时,客户端发 送请求至服务器端并获得一个响应,与响应一起发送的还有状态细节以及 trailer 元数据。
服务器端流RPC模式
在一元 RPC 模式中,gRPC 服务器端和 gRPC 客户端在通信时始终只有一个请求和一个响应。在服务器 端流 RPC 模式中,服务器端在接收到客户端的请求消息后,会发回一个响应的序列。这种多个响应所组 成的序列也被称为“流”。在将所有的服务器端响应发送完毕之后,服务器端会以 trailer 元数据的形式将 其状态发送给客户端,从而标记流的结束。
客户端流RPC模式
在客户端流 RPC 模式中,客户端会发送多个请求给服务器端,而不再是单个请求。服务器端则会发送一 个响应给客户端。但是,服务器端不一定要等到从客户端接收到所有消息后才发送响应。基于这样的逻 辑,我们可以在接收到流中的一条消息或几条消息之后就发送响应,也可以在读取完流中的所有消息之 后再发送响应。
双向流RPC模式
在双向流 RPC 模式中,客户端以消息流的形式发送请求到服务器端,服务器端也以消息流的形式进行响 应。调用必须由客户端发起,但在此之后,通信完全基于 gRPC 客户端和服务器端的应用程序逻辑。
更多资料在:https://github.com/0voice查询