[ RPC框架概念简介 | 青训营笔记]

73 阅读3分钟

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

RPC框架

基本概念

本地函数调用与远程函数调用

  • 本地函数调用

    参数压栈->call->执行目标函数->返回

  • 远程函数调用

    需要解决如下一些问题:

    1. 如何找到目标函数?

      函数映射

    2. 如何传输参数?

      数据序列化

    3. 网络传输

RPC概念模型

1984年Nelson发表的论文中,提出了RPC过程由五个模型组成:

  • User
  • User-Stub
  • RPC-Runtime
  • Server-Stub
  • Server

image.png

实际RPC的一些概念

  • IDL(接口定义语言)
  • 生成代码:通过编译器工具把IDL转换为对应语言的静态库
  • 编解码:内存数据到字节序列的转换
  • 通信协议:除了请求、响应之外,还包含网络传输的元数据
  • 网络传输:通常基于网络库并通过TCP/UDP传输

RPC的优点有哪些?

  1. 单一职责:不同的服务之间相互独立,可以采用不同的技术栈开发并独立开发和运维
  2. 可扩展性强:可以扩展需要的服务,而保持其他服务不变
  3. 故障隔离:服务整体的可靠性更高

RPC带来的问题有哪些?

  1. 被调用方宕机如何处理?
  2. 调用过程中发生网络异常,如何保证消息可达?
  3. 请求量剧增导致无法及时处理时,如何应对?

RPC框架需要解决使用RPC带来的这些问题。

分层设计

Apache Thrift框架的整体架构如下所示

image.png

编解码层

  • 代码生成

    通过IDL文件,生成统一的跨语言的数据格式。

    数据编码格式可以大致分为三类:

    1. 语言内置的序列化例如java的serialize
    2. 人类可读的文本编码例如JSON、XML等
    3. 二进制编码例如protobuf
  • 编码格式的选择

    一般考虑如下一些特性

    • 兼容性(自动增加新字段、而不影响老服务)
    • 通用性:跨平台、跨语言
    • 性能:编解码的时间空间开销

协议层

  • 协议层的分类与概念

    • 特殊结束符:采用特殊结束符作为每个协议单元的结束(例如msg \r\n msg)
    • 变长协议:以定长(协议头)+不定长的部分组成,定长部分需要描述长度
  • 协议的构造

    • HEADER + PAYLOAD
  • 协议解析

    • MagicNumber -> PayloadCodec -> Decode Payload

网络通信层

  • Socket API

    直接使用操作系统提供的API,比较麻烦

  • 使用网络库实现

    • 提供易用的API,包含连接管理和事件分发
    • 功能:支持tcp、udp和uds等,并提供优雅退出和异常处理
    • 性能:采用buffer减少复制,通过对象池、高性能定时器等提高性能

关键指标

稳定性

  • 保障策略:

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

    • 负载均衡
    • 重试
  • 长尾请求(pct99)

    • Backup Request(提前重试)

框架如何实现以上策略呢?通过在框架中注册Middle Ware来实现。

易用性

  • 开箱即用:提供合理的默认配置以及丰富的文档
  • 周边工具:代码生成器、脚手架工具

扩展性

  • 支持MiddleWare

  • 支持多种选项

  • 支持多种

    • 编解码格式
    • 协议
    • 网络传输
  • 代码生成工具插件扩展

观测性

  • Log:日志
  • Metric:监控面板
  • Tracing:链路追踪

在RPC框架中内置观测性服务(例如日志平台、框架配置查看、环境变量等等)

高性能

  • 适配不同场景

  • 性能目标:

    • 高吞吐
    • 低延迟
  • 优化手段

    • 连接池
    • 多路复用
    • 高性能编解码
    • 高性能网络库