gRPC

2015年2月由Google公司牵头,2016年8月对外正式发布的基于HTTP/2以及使用Proto3作为IDL与传输数据格式的通用的开源RPC架构。

我使用kotlin语言写了一个Android与Java后台通过GRPC通信的Demo: Jacksgong/grpc-android-kotlin

And Square, which has been working with Google on gRPC since the very early days, is connecting polyglot microservices within its infrastructure. - gRPC: a true internet-scale RPC framework is now 1.0 and ready for production deployments

I. 特点

  • 低延迟、高拓展、高性能
  • 目前Google、Square等贡献代码
  • 已经在Google云服务、Netflix、CoreOS、Vendasta、Cockroachdb等上使用
  • 基于HTTP/2协议标准设计(双向流、头部压缩、多复用请求、二进制以帧为单位传输等),节省带宽,降低TCP连接次数、节省CPU使用、电池寿命,便于负载均衡、认证、日志监控
  • 使用ProtocolBuffer3(也可以使用proto2)作为IDL(Interface Definition Language)来定义服务以及数据的格式,使用简单快速接入
  • 支持双向通信(Bidirectional Streaming): 可以通过单个gRPC建立的一个stream,使得客户端与服务端可以相互发送消息(有序)
  • 支持同步与异步的RPC
  • 目前支持: C(核心库)、C++、Ruby、NodeJS、Python、PHP、C#、Objective-C(IOS)、Java(后端服务/Android)、go
  • 处理了所有的复杂的:严格的约定、数据序列化、有效的网络通信、安全校验、访问控制、分布式等

gRPC can help make connecting, operating and debugging distributed systems as easy as making local function calls; the framework handles all the complexities normally associated with enforcing strict service contracts, data serialization, efficient network communication, authentications and access control, distributed tracing and so on - gRPC: a true internet-scale RPC framework is now 1.0 and ready for production deployments

II. 安全校验

  • 支持SSL/TLS
  • 支持通过实现gRPC提供的接口来实现自己的校验机制

III. 支持的服务方法

  1. 类似本地调用方法: 客户端发送一个请求然后收到一个响应
  2. 客户端发送一个请求给服务器,并且不断从服务端返回的数据流中读取数据,直到没有数据
  3. 客户端使用stream不断写入一系列的数据并发送给服务端,当客户端完成写入以后等待服务端读取以及服务端的响应
  4. 客户端与服务端通过可读写的stream发送一系列的消息实现双向通信: 两个stream是相互独立的,因此两端可以同时或错开无序的发送与接收数据

IV. 流程

开发流程

  1. 通过proto编写接口
  2. 通过proto编译插件,生成客户端与服务端的代码
  3. 服务端实现在proto中定义的接口, gRPC负责: 解码客户端的请求,执行服务端方法,编码服务端响应
  4. 客户端会有一个本地对象(如stub)其中已经包含了实现,因此客户端只需要调用这些方法,封装请求参数,等待返回即可。

通信流程

  • 客户端可以通过请求的metadata上面的deadline参数告知服务度客户端可以等待响应的时间(超过DEADLINE_EXCEEDED)
  • 服务端与客户端的结束状态可能是不同的,有可能一边是正确结束了,一边却是错误结束的(如客户端发现超时了,刚好服务端那边检测没有超过时间,然后成功了)
  • 异步的RPC方法调用允许客户端或服务端将其随时取消
一般RPC调用通信
  1. 客户端通调用方法访问服务端方法,在metadata上面带上要访问的方法名、deadline等
  2. 服务端可以直接方法初始化metadata 或 等待并接收客户端发送请求数据
  3. 服务端获执行相关操作生成响应数据、状态码,状态信息、结束的metadata等
  4. 客户端收到响应,完成调用
双向通信

利用gRPC做push通道: Question about events or push notification

  1. 客户端通调用方法访问服务端方法,在metadata上面带上要访问的方法名、deadline等
  2. 服务端可以直接方法初始化metadata 或 等待并接收客户端发送请求数据
  3. 客户端与服务端可以无序的独立完成读写操作
  4. 服务端与客户端可以开始相互的发送消息

具体双向通信流程

  • 客户端到服务端: 带上Call Header, 以及optional的Initial-Metadata, 0Payload Messages数据
  • 服务端到客户端: 带上optional的Initial-Metadata, 以及0Payload Messages数据
  • 结束: 带上Status,以及optional的Status-Metadata (也称为Trailing-Metadata)

其中的数据结构

  • gPRC的双向stream是直接映射HTTP/2的stream,其中的每个请求的id是对应stream的id
  • Call HeaderInitial Metadata使用HTTP/2的headers发送因此也采用HPACK压缩
  • Payload Messages将映射为字节流,在发送端组装为HTTP/2帧,在接收端重新组装为数据
  • StatusTrailing-Metadata是通过HTTP/2的trailing headers进行传输

V. PING帧

  • 在deadline之内如果发送PING没有收到响应,服务端就会于CANCELLED状态直接结束所有操作,如果是客户端就会以UNAVAILABLE状态结束
  • 发送PING的频率取决于网络环境,也可以自由的进行调整

VI. 案例

VII. 其他

gRPC比较Thrift

  • gRPC基于最新的HTTP2公有协议,(Thrift采用私有协议),gRPC更好做维护、性能优化、缓存、集群
  • gRPC采用proto3.x作为IDL,更易于配置
  • gRPC采用proto3.x作为传输数据的数据结构,序列化,反序列化速度比thrift稍好
  • gRPC目前社区逐渐活跃,
  • gRPC是非常与Google内部类似已经使用许多年的版本,但Thrift虽然在2007年就release了,但是内部很多重要的迭代Facebook拒绝贡献到开源社区中
  • Facebook到后面就都没有维护Thrift了,都丢给社区维护了,不过14年的时候自己建了一个使用C++写的fbThrift

gRPC使用反向代理

Nginx

gRPC-PHP是可以的,但是其余的(如gRPC-Java目前暂时不行,但是正在实现)

其他方案



Jacksgong wechat
欢迎关注Jacks Blog公众号,第一时间接收原创技术沉淀干货。