Chapter 4. gRP: Under the hood
RPC Flow
- client 使用生成的 stub 调用 getProduct 函数。
- client stub 使用编码消息创建一个 HTTP POST 请求。在 gRPC 中,所有的请求都是 HTTP POST请求,其 content-type 的前缀是 application/grpc。 客户端调用的远程函数作为一个单独的 HTTP Header 被发送。
- HTTP 请求消息通过网络被发送到 server 机器上。
- 当消息被服务器接收时,服务器检查消息的 header 来查看哪个服务函数需要被调用,并将消息移交给 service stub。
- service stub 将字节消息解析为语言指定的数据结构。
- 然后,使用解析的数据,service 对 getProduct 函数做本地调用。
- 来自 service 函数的响应被编码并发送回 client,response->encode->HTTP response on the wire。消息被解包,它的值被返回到等待的 client 进程。
Message Encoding Using Protocol Buffers
使用 protocol buffers 定义服务包含定义服务中的远程方法,和定义消息结构。
message ProductID {
string value = 1;
}
消息实体的编码表示由字段标识符(tag),后跟编码后的字段值组成。
Tag 由两部分组成:field index 和 wire type。field index 是在定义消息字段时赋值的唯一数字。wire type 基于 field type,它提供计算值长度的信息。
Encoding Techniques
Varints
Varints 分配变长字节来表示一个值。
Signed integers
使用 zigzag 编码将有符号整数转换无符号整数,然后使用 Varints 对无符号整数进行编码。
负整数映射为奇数,正整数映射为偶数。
Nonvarint numbers
以定长字节表示数字值。64 位数据类型,fixed64,sfixed64 和 double。32 位数据类型,fixed32,sfixed32 和 float。
String type
string 类型是限定长度的 wire type,为 varint-encoded 的长度值后跟指定字节数的数据。string 值使用 UTF-8 字符编码方式。
Length-Prefixed Message Framing
gRPC 使用的 message-framing 技术称为 length-prefix framing,即先写入消息的长度,再写入消息本身。
消息长度为 4 字节,表示 gRPC 消息的大小至多 4 GB。
gRPC over HTTP/2
gPRC channel 本质是 HTTP/2 的连接;gRPC 远程调用被映射到 HTTP/2 的流中。
Request Message
Client 发送 Request Headers 标识 RPC 的开始,然后发送 Length-Prefixed-Message,最后发送 EOS 标识 RPC 请求结束。
- 定义 HTTP method。gRPC 总是使用 POST,表示请求使用目标资源处理 representation。
- 定义 HTTP scheme。如果启用 TLS(Transport Level Security),sheme 被设为 “https”,否则未 “http”。
- 定义 endpoint path。对于 gRPC 来说,为 “/”{service name}“/”{method name}。
- 定义 target URI 的 virtual hostname。
- 定义不兼容代理的检测。对于 gRPC,该值必须是 “trailers”。
- 定义调用超时。如果没有指定,服务器应当假设超时为无限时间。
- 定义 content-type。对于 gRPC,content-type 应当为 application/grpc。否则,服务会返回状态码 415 (Unsupported Media Type)。
- 定义消息压缩类型。可能的值为 identity,gzip,deflate,snappy,和 {custom}。
- 这是一个可选的 metadata。authorization metadata 被用于访问安全终端。
一些其他的需要注意的点:
- 以 “:” 起始的 Header 被称为保留的 header,HTTP/2 要求保留 header 出现在其他 header 之前。
- 在 gRPC 通讯中的传递的 headers 被分为两类:调用定义 header 和自定义 metadata。
- Call-definition header HTTP/2 支持的预定义 header。它应当在自定义 metadata 之前发送。
- 自定义 metadata 是任意的键值对,由应用层定义。当你定义自定义 metadata 时,你需要保证不使用以 grpc- 起始的 header。它们被保留由 gRPC core 使用。
client 先发送 request header,再发送 length-prefixed message(可以分为多个 frame),最后以 EOS 结束本次 HTTP 请求。
Response Message
Response Message 由三部分组成:Response Headers,Length-Prefixed Message 和 Trailers。
- 表明 HTTP 请求的状态。
- 定义消息压缩类型。可能的值为 identity,gzip,deflate,snappy,和 {custom}。
- 定义 content-type。对于 gRPC,content-type 应当为 application/grpc。
与 request header 类似,应用层定义的自定义 metadata 包含任意的键值对,它们能被设置到 response header 中。
发送 response header 后,会使用单独的一个或几个 HTTP/2 data frame 发送 length-prefixed 消息,但是最后一个 HTTP/2 data frame 不会设置 END_STREAM flag,它在另外一个称为 trailer 的 header 中设置。
最后,发送 trailers 来表示 response message 发送完成,它包含请求的 status code 和 status message。
- 定义 gRPC 状态码。
- 定义错误描述,这是可选的,仅在处理请求过程中发生错误才定义。
特定情况下,client 的请求调用可能会立刻失败,此时,server 仅发送 trailers 作为 response。它依然包含 gRPC status 和 status message,此外,它还包含其他的 header,因为只返回一个 HTTP/2 header。它包含 END_STREAM 和 END_HEADERS flags。
- HTTP-Status->:status
- Content-Type->content-type
- Status->grpc-status
- Status-Message->grpc-message
Understanding the Message Flow in gRPC Communication Patterns
Simple RPC
Server-streaming RPC
Client-streaming RPC
Bidirectional-streaming RPC
gRPC Implementation Architecture
Summary
gRPC 构建与 protocol buffer 和 HTTP/2 之上。
protocol buffer 是一个数据序列化协议,它生成的二进制 payload 较 json 格式更小且是强类型的。
HTTP/2 用于传输 protocol buffer 生成的二进制 payload。HTTP/2 是多路复用的,它支持在单个 TCP 连接上存在多个数据流。