gRPC 源码分析 (一) : 概述
gRPC 源码分析这个系列的文章记录了我在阅读学习 gRPC 源代码过程中的想法和发现, 阅读 gRPC 源代码,一方面是因为在工作中经常会用到 gRPC, 所以希望能够深入了解它底层的实现原理来更高效地去使用它, 另一方面, 也可以从源代码中一窥 gRPC 的设计者在构建这样一个高性能的 RPC 框架时的一些想法, 想想假如是我们来设计 gRPC, 它应该是什么样子的.
文章系列会借助于分析源码, 大体介绍 gRPC 连接中, client 和 server 之间是如何建立连接, 以及一个 gRPC call 完整的流程. 之后会逐个讨论 gRPC 中比较关键的功能是如何实现的, 并探究 gRPC 高性能的秘密.
系列文章中所列的源代码均来自 github.com/grpc/grpc-g…. 其中部分源代码过长, 因此只截取了和讨论主题相关的部分代码.
作为 gRPC 源码分析的第一章, 我们一起来大概了解一下 gRPC server 和 client 是如何建立连接并发送消息的.
gRPC 流程概括
在 gRPC 中, 可以将 gRPC 的流程大致分为两个阶段, 分别是 RPC 连接阶段, 以及 RPC 交互阶段.
- 在 RPC 连接阶段, client 和 server 之间建立起来 TCP 连接, 并且由于 gRPC 底层依赖于 HTTP2, 因此 client 和 server 还需要协调 frame 的相关设置, 例如 frame 的大小, 滑动窗口的大小等等.
- 在 RPC 交互阶段, client 将数据发送给 server, 并等待 server 执行指定 method 之后返回结果.
Client 的流程
在 RPC 连接阶段, client 接收到一个目标地址 (string) 和一系列的 DialOptions, 然后
- 配置连接参数, interceptor 等, 启动 resolver.
- Resolver 根据目标地址获取 server 的地址列表 (比如一个 DNS name 可能会指向多个 server ip, dnsResovler 是 gRPC 内置的 resolver 之一). 启动 balancer.
- Balancer 根据平衡策略, 从诸多 server 地址中选择一个或多个建立 TCP 连接.
- client 在 TCP 连接建立完成之后, 等待 server 发来的 HTTP2 Settings frame, 并调整自身的 HTTP2 相关配置. 随后向 server 发送 HTTP2 Settings frame.
在 RPC 交互阶段,某个 local method 被调用之后,
- Client 创建一个 stream 对象用来管理整个交互流程.
- Client 将 service name, method name 等信息放到 header frame 中并发送给 server.
- Client 将 method 的参数信息放到 data frame 中并发送给 server.
- Client 等待 server 传回的 header frame 和 data frame. 一次 RPC call 的 result status 会被包含在 header frame 中, 而 method 的返回值被包含在 data frame 中.
Server 流程
在 RPC 连接阶段, server 在完成一些初始化的配置之后, 开始监听某个 TCP 端口. 在和某个 client 建立了 TCP 连接之后完成 HTTP2 settings frame 的交互.
在 RPC 交互阶段,
- Server 等待 client 发来的 header frame, 从而创建出一个 stream 对象来管理整个交互流程. 根据 header frame 中的信息, server 知道 client 请求的是哪个 service 的哪个 method.
- Server 接收到 client 发来的 data frame, 并执行 method.
- Server 将执行是否成功等信息方法放在 header frame 中发送给 client.
- Server 将 method 执行的结果 (返回值) 放在 data frame 中发送给 client.
总结
本章中我们大概了解了 server 和 client 在连接 RPC 流程中都经历了哪些步骤, 下一片文章将讨论 server 在 RPC 连接阶段所做的事情.