vlambda博客
学习文章列表

grpc教程(三)grpc的底层原理


grpc构建在两个快速高效的协议之上,也就是protocol buffers和http/2。

protocol buffers是一个语言中立,平台无关的数据序列化协议。当序列化完成,该协议会生成二进制载荷,这种载荷波json载荷更小,并且是强类型的。

HTTP/2http的第二个主版本,完全多路复用意味着http/2可以在tcp连接上并行发送多个数据请求。


01

通过网络实现rpc流程


以下是grpc调用时一个简单的流程:

1.客户端进程通过protoc生成的编码的stub,并调用具体方法。

2.客户端用已编码的消息创建HTTP POST请求。

在grpc中,所有的请求都是HTTP/POST请求,并且content-type前缀为application/grpc,要调用的远程方法是以单独的HTTP头信息发送的。

3.HTTP请求通过网络发送到服务器端。

4.服务端接收到消息后检查头信息,从而确定需要调用的服务方法,然后将消息传递给服务器处理。

5.服务器将消息字节解析成特定语言的数据结构。

6.服务器骨架对解析后的方法进行本地调用。



02


使用protocol buffers编码


使用protocol buffers编码消费

grpc使用proto文件编写服务定义,使用protocol buffers定义服务。proto语法有proto2和proto3版本,它们之间还是有区别的。

比如制定变量规则,在 proto3 中,可以给变量指定以下两个规则:

singular:0或者1个,但不能多于1个。

repeated:任意数量(包括0)当构建 message 的时候,build 数据的时候,会检测设置的数据跟规则是否匹配。

在proto2中,规则为:

required:必须有一个

optional:0或者1个

repeated:任意数量(包括0)


例子:

// 指定使用proto3,如果不指定的话,编译器会使用proto2去编译syntax = "proto3"; //[proto2|proto3]
message SearchRequests { // 定义SearchRequests的成员变量,需要指定:变量类型、变量名、变量Tag string query = 1; int32 page_number = 2; int32 result_per_page = 3;}



在创建消息实例的过程时,对应的字节内容会包含一个用于字段的标识符,随后是其编码的值。在字段的标识符也被称为标签(tag)。

标签由两个值构成:字段索引和线路类型。

字段索引就是在proto文件中定义消息时,为每个消息字段所设置的唯一数字。线路类型是基于字段类型,也就是能够为字段输入值的数据类型。线路类型会提供信息来确定值,会占3位。


protocol buffers支持各种字段类型,有些字段类型有不同的编码机制。比如int32,int64,uint32,uint64,sint32(高效编码负数),sint64(高效编码负数)


基于长度前缀的消息分帧

消息分帧会构建消息和通信,以便于目标受众很容易提取信息,对于grpc使用了长度前缀分帧的消息分帧技术。

长度前缀分帧是指在写入消息本身前,根据消息的proto定义写入长度信息来表明每条信息的大小。在grpc中每条消息有额外的4字节用来设置其大小,也就意味grpc通信可以处理大小不超过4GB的所有消息。


所以一旦更改了proto消息中的字段类型,其实会影响整个消息队列的,客户端接收到的消息不仅仅是单个字段不可用,而是整个消息都因错乱而解析不了。

因此使用grpc时,一定要保持协议一致。


03


基于http/2的grpc

在http/2中客户端和服务器所有通信都是通过一个tcp连接完成的,这个连接可以传送任意数量的双向字节流。

一些基本概念:

流:在一个建立的连接上的双向字节流,一个流可以携带一条或多条消息。

帧:http/2中最小的通信单元,每一帧都包含一个帧头,它至少要标记该帧所属的流。

消息:完整的帧序列,映射一条逻辑上的http消息。由一帧或多帧组成。这样的话,允许消息进行多路复用,客户端和服务端能将消息分解成独立的帧,交叉发送它们,然后在另一端进行重新组合。


http/2的基本解释(此处来源网络):

HTTP/2主要是为了解决现HTTP 1.1性能不好的问题才出现的。当初Google为了提高HTTP性能,做出了SPDY,它就是HTTP/2的前身,后来也发展成为HTTP/2的标准。

HTTP/2兼容HTTP 1.1,例如HTTP Method,Status code,URI以及大部分Header Fields。

HTTP/2通过以下方法减少延迟,用来改进页面加载的速度,

  1. HTTP Header的压缩采用的是HPack算法。

  2. HTTP/2的Server Push,非常重要的一个特性。

  3. 请求的pipeline。

  4. 修复在HTTP 1.x的队头阻塞问题。

  5. 在单个TCP连接里多工复用请求。

HTTP/2支持HTTP 1.1里的大部分use case,例如桌面浏览器、移动浏览器、Web API、Web Server、代理服务器、反向代理服务器、防火墙和CDN等。