1. gRPC 概念
gRPC
是 Google
开源的一款高性能的 RPC
框架。GitHub
上介绍如下:
gRPC is a modern, open source, high-performance remote procedure call (RPC) framework that can run anywhere.
在每个gRPC 发布版本中,字母 g 的含义都不同。比如 1.1 版本的 g 代表 good(优秀),1.2 版本的 g 代表 green(绿色)
gRPC
能够在众多的框架中脱颖而出,是跟其高性能是密切相关的。
服务定义是在
ProductInfo.proto
文件中声明的,服务器端和客户端都会使用该文件来生成代码。
2. gRPC 特点
2.1 接口设计
gRPC
为应用程序开发提供了一种契约优先的方式。也就是说,首先必须定义服务接口,然后才能去处理实现细节。
对一个远程服务 Service
的调用,gRPC
约定 Client
和 Server
首先需要约定好 Service
的结构。包括一系列方法的组合,每个方法定义、参数、返回体等。
对这个结构的描述,gRPC
默认是用 Protocol Buffer
去实现的。
2.2 Streaming
Streaming
在 HTTP/1.x
已经出现了,HTTP2
实现了 Streaming
的多路复用。gRPC
是基于 HTTP2
实现的。所以 gRPC
也实现了 Streaming
的多路复用,所以 gRPC
的请求有四种模式:
- Simple RPC
- Client-side Streaming RPC
- Server-side Streaming RPC
- Bidirectional Streaming RPC
也就是说同时支持单边流和双向流。
2.3 Protocol
gRPC
的协议层是基于 HTTP2
设计的,所以你如果想了解 gRPC
的话,可以先深入了解 HTTP2
。
gRPC
使用 protocol buffers
作为接口定义语言 IDL(interface definition language)
来定义服务接口。
protocol buffers
是语言中立、平台无关、实现结构化数据序列化的可扩展机制。服务接口定义在 proto
文件中指定,也就是在扩展名为 .proto
的普通文本文件中。
我们要按照普通的 protocol buffers
格式来定义 gRPC
服务,并将RPC
方法参数和返回类型指定为 protocol buffers
消息。
因为服务定义是 protocol buffers
规范的扩展,所以可以借助特殊的 gRPC
插件来根据proto
文件生成代码。
2.4 Flow Control
gRPC
的协议支持流量控制,这里也是采用了 HTTP2
的 Flow Control
机制。通过上面的介绍可以看到,gRPC
的高性能很大程度上依赖了 HTTP2
的能力,所以要了解 gRPC
之前,我们需要先了解一下 HTTP 2
的特性。
gRPC
在客户端和服务器端都提供了对流的原生支持,gRPC
的关键优势就是能够同时构建传统的请求–响应风格的消息以及客户端流和服务器端流。
2.5 HTTP2 特性
- 二进制协议
众所周知,二进制协议比文本形式的协议,发送的数据量肯定是更小,传输效率更高的。所以 HTTP2
比 HTTP/1.x
更高效,因为二进制是不可读的,所以会损失部分可读性。
- 多路复用的流
HTTP/1.x
一个 Stream
是需要一个 TCP
连接的,其实从性能上来说是比较浪费的。HTTP2
可以复用 TCP
连接,实现一个 TCP
连接可以处理多个 Stream
,同时可以为每一个 Stream
设置优先级,可以用来告诉对端哪个流更重要。当资源有限的时候,服务器会根据优先级来选择应该先发送哪些流。
- 头部压缩
由于 HTTP
协议是一个无状态的协议,导致了很多相同或者类似的 HTTP
请求重复发送时,带的头部信息很多时候是完全一样的。HTTP2
对头部进行压缩,可以减少数据包大小,提高协议性能。
- 请求 Reset
在 HTTP/1.x
中,当一个含有确切值的 Content-Length
的 HTTP
消息发出之后,需要断开 TCP
连接才能中断。这样会导致需要通过三次握手来重新建立一个新的 TCP
连接,代价是比较大的。在 HTTP2
里面,我们可以通过发送 RST_STREAM
帧来终止当前消息发送,从而避免了浪费带宽和中断已有的连接。
- 服务器推送
如果一个 Client
请求资源 A
,而 Server
知道 Client
可能也会需要资源 B
, 所以在 Client
发起请求前,Server
提前将 B
推送给 A
缓存起来,从而可以缩短资源 A
这个请求的响应时间。
- Flow Control
在 HTTP2
中,每个 HTTP Stream
都有自己公示的流量窗口,对于每个 Stream
来说,Client
和 Server
都必须互相告诉对方自己能够处理的窗口大小,Stream
中的数据帧大小不得超过能处理的窗口值。
2.6 商业化高级特性
gRPC
提供了对商业化特性的内置支持,如认证、加密、弹性(截止时间和超时)、元数据交换、压缩、负载均衡、服务发现等。
3. gRPC 调用流程
- 客户端进程通过生成的存根调用
getProduct
方法。 - 客户端存根使用已编码的消息创建
HTTP POST
请求。在gRPC
中,所有的请求都是HTTP POST
请求,并且content-type
前缀为application/grpc
。要调用的远程方法 (/ProductInfo/getProduct)是以单独的HTTP
头信息的形式发送的。 HTTP
请求消息通过网络发送到服务器端。- 当接收到消息后,服务器端检查消息头信息,从而确定需要调用的服务方法,然后将消息传递给服务器端骨架。
- 服务器端骨架将消息字节解析成特定语言的数据结构。
- 借助解析后的消息,服务发起对
getProduct
方法的本地调用。
服务方法的响应经过编码后被发送回客户端。响应消息会遵循我们在客户端上所观察到的相同过程(响应→编码→线路上的 HTTP 响应),该消息会被解包,它的值将返回给等待的客户端进程。