深入浅出RPC框架 | 青训营笔记

161 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记

基本概念

  • 相比本地函数调用,RPC调用需要解决的问题

    • 函数映射
  • 数据转换成字节流
  • 网络传输

RPC的概念模型

  • IDL (Interface description language)文件通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信

一次完整的RPC过程

  • 生成代码

通过编译器工具把IDL文件转换成对应的静态库

  • 编解码

从内存中表示字节序列的转换成为编码,反之叫解码,也可以叫做序列化和反序列化。

  • 通信协议

规范了数据在网络中的传输内容和格式,出必须的请求。响应数据外,通常包含额外的元数据

  • 网络传输

通常基于成熟的网络库走TCP/UDP传输

RPC的好处以及缺点

  • 好处
  1. 单一职责,有利于分工协作和运维开发
  2. 可扩展性强,资源利用率高
  3. 故障隔离,服务整体可靠性更高

  • RPC 带来的问题将由 RPC 框架来解决

    • 服务宕机如何感知?
  • 遇到网络异常应该如何应对?
  • 请求量暴增怎么处理?

RPC 框架分层设计

编解码层

  • 生成代码

  • 数据格式

语言特定格式:例如 java.io.Serializable

文本格式:例如 JSON、XML、CSV 等

二进制编码:常见有 Thrift 的 BinaryProtocol,Protobuf,实现可以有多种形式,例如 TLV 编码 和 Varint 编码

  • 选型考察点

    • 兼容性:支持自动增加新的字段,而不影响旧的服务,提高了系统的灵活度
  • 通用型:支持跨平台、跨语言
  • 时间开销
  • 生成代码和编解码层相互依赖,框架的编解码应当具备扩展任意编解码协议的能力

协议层

  • 特殊结束符

一个特殊字符作为每个协议单元结束的标识

  • 变长协议

以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度

  • LENGTH 字段 32bits,包括数据包剩余部分的字节大小,不包含 LENGTH 自身长度
  • HEADER MAGIC 字段16bits,值为:0x1000,用于标识协议版本信息,协议解析的时候可以快速校验
  • FLAGS 字段 16bits,为预留字段,暂未使用,默认值为 0x0000
  • SEQUENCE NUMBER 字段 32bits,表示数据包的 seqId,可用于多路复用,最好确保单个连接内递增
  • HEADER SIZE 字段 16bits,等于头部长度字节数/4,头部长度计算从第14个字节开始计算,一直到 PAYLOAD 前(备注:header 的最大长度为 64K)
  • PROTOCOL ID 字段 uint8 编码,取值有: - ProtocolIDBinary = 0 - ProtocolIDCompact = 2
  • NUM TRANSFORMS 字段 uint8 编码,表示 TRANSFORM 个数
  • TRANSFORM ID 字段 uint8 编码,表示压缩方式 zlib or snappy
  • INFO ID 字段 uint8 编码,具体取值参考下文,用于传递一些定制的 meta 信息
  • PAYLOAD 消息内容

协议解析:

网络通信层

  • Sockets API

  • 网络库

    • 提供易用API

封装底层Socket API

连接管理和事件分发

  • 功能

协议支持:tcp、udp和uds

优雅退出、异常处理

  • 性能

应用层buffer减少copy

高性能定时器、对象池

RPC框架核心指标

稳定性

  • 保障策略

    • 熔断:保护调用方,防止被调用的服务出现问题而影响整个链路
  • 限流:保护被调用方防止大量流量把服务压垮
  • 超时控制:避免浪费资源在不可用的节点上

从某种程度上讲超时、限流和熔断也是一种服务降级的手段 。

  • 请求成功率

    • 负载均衡

  • 重试

  • 长尾请求

    • BackupRequest

易用性

  • 开箱即用

    • 合理的默认参数选项、丰富的文档
  • 周边工具

    • 生成代码工具、脚手架工具

扩展性

  • Middleware:middleware 会被构造成一个有序调用链逐个执行,比如服务发现、路由、负载均衡、超时控制等
  • Option:作为初始化参数
  • 核心层是支持扩展的:编解码、协议、网络传输层
  • 代码生成工具也支持插件扩展

观测性

  • 三件套:Log、Metric 和 Tracing

  • 内置观测性服务,用于观察框架内部状态

    • 当前环境变量
  • 配置参数
  • 缓存信息
  • 内置 pprof 服务用于排查问题

高性能

  • 连接池和多路复用:复用连接,减少频繁建联带来的开销
  • 高性能编解码协议:Thrift、Protobuf、Flatbuffer 和 Cap'n Proto 等
  • 高性能网络库:Netpoll 和 Netty 等