RPC 学习 | 青训营笔记

74 阅读4分钟

RPC概念

image-20230523140802910

IDL文件(Interface description langurage)

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

生成代码

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

编解码

从内存中表示到字节序列的转换成为编码,反之为解码, 也称为序列化和反序列化

通信协议

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

网络传输

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

image-20230523140840126

RPC优点

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

出现的问题

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

image-20230523145748147

编解码层-数据格式

  • 语言特定的格式

    将内存对象编码为字节序列的支持

  • 文本格式

    JSON、XML、CSV等文本格式

  • 二进制编码

    具备跨语言和高性能等优点,常见有Thrift的BinaryProtocol、 Protobuf等

    • TLV编码

      • Tag:标签
      • Length:长度
      • Value: 值
      struct{
      1: required string         userName,
      2: optional i64            favoriteNumber,
      3: optional list<string>   interessts,
      }
      
  • 选型
    • 兼容性

      支持自动增加新的字段,不影响老的服务,提高系统的灵活性

    • 通用性

      支持跨平台、跨语音

    • 性能

      从空间和时间两个维度考虑,编码后数据大小和编码耗费时长

协议层

  • 概念
    • 特殊结束符

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

    • 变长协议

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

  • 协议解析

网络通信层

image-20230523152926525

  • 网络库
    • 提供易用的API
      1. 封装底层Socket API
      2. 连接管理和事件分发
    • 功能
      1. 协议支持:tcp、udp和uds
      2. 优雅退出、异常处理
    • 性能
      1. 应用层buffer 减少copy
      2. 高性能定时器、对象池等

image-20230523153953630

RPC的稳定性

保障策略(应对流量高峰)

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

请求成功率

  1. 负载均衡
  2. 重试

长尾请求

image-20230523162018947

注册中间件 保障服务的稳定性

RPC的易用性

  1. 开箱即用

    合理的默认参数选项、丰富的文档

  2. 周边工具

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

RPC的扩展性

  • Middleware
  • Option
  • 编解码层
  • 协议层
  • 网络传输层
  • 代码生成工具插件扩展

image-20230523162709632

观测性

  • Log、Metric、Tracing
  • 内置观测性服务

image-20230523164348849

Kitex 整体框架

image-20230523165117291

image-20230523171629200image-20230523171629200

性能优化-网络库优化

  • 调度优化

    1. epoll_wait 在调度上的控制
    2. gopool重用goroution 降低同时运行协程数
  • LinkBuffer

    1. 读写并行无锁, 支持nocopy 地流式读写
    2. 高效扩缩容
    3. Nocopy Buffer池化, 减少GC
  • Pool

    1. 引入内存吃和对象池,减少GC开销

性能优化-编解码优化

  • CodeGen

    与计算并分配内存,减少内存操作次数,包括内存分配和拷贝

    linline减少函数调用次和避免不必要的反射操作

    Thrift IDL解析和代码生成器, 支持完善的Thrift IDL语法和语义检查

  • JIT (及时编译,just int time) 当代码第一次使用时进行编译

    无需生成代码

    传统的 Thrift 编解码方式,要求用户必须要先生成编解码代码,Frugal 通过 JIT 编译技术在运行时动态生成编解码机器代码,避免了这一过程。

    1. 使用JIT编译技术 改善用户体验的同时带来更强的编解码性能,减轻用户维护生成代码的负担
    2. 基于JIT 编译技术的高性能动态Thrift 编解码器 - Frugal

合并部署

微服务多小, 传输和序列化开销过大。

将亲和性强的服务实例调度在同一个物理机, 远程RPC 调用优化为本地IPC调用。

  1. 中心化的部署调度和流量控制
  2. 基于共享内存的通信协议
  3. 定制化的服务发现和连接池实现
  4. 定制化的服务启动和监听逻辑