后端 RPC原理与实现 day17 | 青训营笔记

187 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天

今日笔记内容: RPC原理与实现

基本概念

本地函数调用原理

  1. 参数压栈, 返回地址
  2. 根据函数指针将pc跳转到函数代码对应地址
  3. 取出参数
  4. 为本地变量分配栈空间
  5. 进行函数运算, 并将返回值压入栈中
  6. 回到调用函数

RPC要解决的问题

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

Nelson在1984年在论文"Implementing Remote Procedure Calls"中提出了RPC的概念模型, 包括User, UserStub, RPC-Runtime, ServerStub, Server

![[Pasted image 20230209214248.png]] RPC的流程

  • IDL文件, 以平台无关的方式定义接口
  • 生成代码, 将IDL文件生成对应语言的源代码
  • 编解码
  • 通信协议
  • 网络传输

RPC的好处

  1. 单一职责
  2. 可拓展性强
  3. 故障隔离

RPC带来的问题

  1. 服务宕机, 调用者如何处理
  2. 调用过程中发生网络异常, 保证消息的可达性
  3. 请求量突增导致服务无法及时处理

分层设计

  • 用户代码
  • IDL生成代码
  • 数据编解码
  • 传输协议
  • 网络通信

编解码层的数据格式

  • 语言特定的格式, 如java中的Serializable
  • 文本格式, JSON, XML, CSV等
  • 二进制编码, 如Thrift的BinaryProtocal, Protobuf等
    • TLV 编码
      • Tag: 标签, 标识类型
      • Length: 长度
      • Value: 值, 也可以嵌套TLV

编解码层的要求

  • 兼容性: 协议新增字段不影响老服务
  • 通用性: 跨平台, 跨语言使用
  • 性能: 编码后的大小和编码时长

协议层: (最熟悉的TCP协议, 定义了两端通信的方式)

  • 特殊结束符(表示包结束)
  • 变长协议(length+payload)

协议构造 ![[Pasted image 20230209215700.png]]

  • Length: 数据包大小
  • Header Magic: 协议版本号, 魔数, 用于解析时快速校验
  • Flags: 控制位
  • Sequence Number: 标识数据包id, 可以用于多路复用, 单条链路中顺序递增
  • Header Size: 变长头部时, 标识头部长度
  • Protocol: 编解码方式, Binary, Compact
  • Transform: 压缩方式, 如zlib, snappy
  • Info: 额外信息
  • Payload: 消息体

网络通信层: socket api

  • 提供易用的API: 封装底层的SocketAPI, 连接管理和事件分发
  • 功能: 多种协议支持. 连接状态管理, 优雅退出, 异常处理等
  • 性能: 应用层buffer减少copy, 高性能定时器, 对象池等

关键指标

稳定性:

  • 熔断: 保护调用方, 防止被调用服务出现问题导致整个链路不可用

  • 限流: 保护被调用方, 防止大流量把服务压垮

  • 超时控制: 浪费资源在不可用节点上

  • 降级

  • 调用成功率

    • 负载均衡
    • 重试(链路放大风险: 单点重试/链路重试上限
  • 长尾请求: P99, 超出该时间后再次发送请求

  • 易用性

  • 可拓展性

  • 可观测性

    • Log
    • Metric
    • Tracing
    • 内置观测服务
  • 高性能

通过中间件实现稳定性策略

企业实践

自研网络库: Netpoll

原生网络库问题

  • 原生库无法感知连接状态

  • 存在goroutine暴涨的风险: 连接与goroutine是1:1的

  • 引用epoll主动监听, 感知连接状态

  • goroutine池, 复用goroutine

  • nocopy buffer 提升性能, 编码层面0拷贝