这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记
本文是对深入浅出 RPC 框架课程主要内容的整理
基本概念
-
相比本地函数调用,RPC调用需要解决的问题
- 函数映射
- 数据转换成字节流
- 网络传输
-
一次 RPC 的完整过程
- RPC过程由5个模型组成:User、User-Stub、RPC-Runtime、Server-Stub、Server
-
RPC的好处
- 单一职责,开发、部署以及运维都是独立的
- 可扩展性强,压力过大时可以独立扩展资源,底层基础服务可以复用,节省资源
- 某个模块发生故障,不会影响整体的可靠性
-
RPC 带来的问题将由 RPC 框架来解决
- 服务宕机如何感知?
- 遇到网络异常应该如何应对?
- 请求量暴增怎么处理?
RPC 框架分层设计
-
以Apache Thrift为例
编解码层
-
数据格式
- 语言特定格式:例如 java.io.Serializable,好处是非常方便,可以用很少的额外代码实现内存对象的保存与恢复。但是这类编码通常与特定的编程语言深度绑定,其他语言很难读取这种数据。此外还有安全性和兼容性的问题。
- 文本格式:例如 JSON、XML、CSV 等,优点在于可读性强,但数字编码多有歧义之处,如XML和CSV不能区分数字和字符串;JSON不能区分整数和浮点数,且不能指定精度。JSON在一些语言中的序列化和反序列化需要采用反射机制,所以性能也比较差。
- 二进制编码:常见有 Thrift 的 BinaryProtocol,Protobuf,实现可以有多种形式,例如 TLV 编码 和 Varint 编码
RPC 框架核心指标
稳定性
框架通过中间件来注入各种服务治理策略,保障服务的稳定性
-
保障策略
- 熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路(服务雪崩)
- 限流:保护被调用方,防止大流量把服务压垮
- 超时控制:避免浪费资源在不可用节点上
-
请求成功率
- 负载均衡
- 重试,重试由于会将流量导入另外一台物理机上,可能会有放大故障的风险
-
长尾请求
-
长尾请求总是会存在,造成长尾请求的原因包括网络抖动、GC、系统调度等
-
预先设定阈值 t3,当Req1发出去t3时间都没有返回,直接发起重试请求Req2。相当于有两个请求同时运行,任何一个成功返回后就可以立即结束这次请求。整体耗时t4相比与超时后再请求,大大减少了时延
-
易用性
-
开箱即用
- 合理的默认参数选项、丰富的文档
-
周边工具
- 生成代码工具、脚手架工具
扩展性
- Middleware:middleware 会被构造成一个有序调用链逐个执行,比如服务发现、路由、负载均衡、超时控制等
- Option:作为初始化参数
- 核心层是支持扩展的:编解码、协议、网络传输层
- 代码生成工具也支持插件扩展
观测性
-
三件套:Log、Metric 和 Tracing
-
内置观测性服务,用于观察框架内部状态
- 当前环境变量
- 配置参数
- 缓存信息
- 内置 pprof 服务用于排查问题
高性能
- 连接池和多路复用:复用连接,减少频繁建联带来的开销
- 高性能编解码协议:Thrift、Protobuf、Flatbuffer 和 Cap'n Proto 等
- 高性能网络库:Netpoll 和 Netty 等