课程笔记:RPC 关键指标 | 青训营笔记

146 阅读3分钟

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

课程笔记:RPC 关键指标

关键指标

稳定性

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

请求成功率

提高成功率方式:

  1. 负载均衡 当有多个节点时均衡各个节点的负载
  2. 重试 调用失败时重试,在多次重试失败后才算真正失败

长尾请求

明显高于平均响应时间的请求

解决方式:备份请求

普通重试:

img.png

(总共需t1+t2) 备份请求:

img_1.png

(按以往经验平均返回时间为t3,总共需t4时间)

注册中间件

通过注册中间件,实现熔断等功能,以保证稳定性

易用性

  1. 开箱即用 合理的默认参数选项、丰富的文档;无需过多配置即可快速使用
  2. 周边工具 生成代码工具、脚手架工具

扩展性

  1. Middleware
  2. Option
  3. 编解码层
  4. 协议层
  5. 网络传输层
  6. 代码生成工具插件扩展

img_2.png

可观测性

  1. Log、Metric(监控面板)、Tracing(链路跟踪)
  2. 内置观测性服务

高性能

场景

  1. 单机多机
  2. 单连接多连接
  3. 单/多Client 单/多Server
  4. 不同大小请求包
  5. 不同请求类型,如PingPong、Streaming等

目标

  1. 高吞吐
  2. 低延迟

手段

  1. 连接池
  2. 多路复用
  3. 高性能编解码协议
  4. 高性能网络库

企业实践

整体架构

  1. Kitex Core 核心组件
  2. Kitex Byted 与公司内部基础设施集成
  3. Kitex Tool 代码生成工具

img_3.png

自研网络库

背景

  1. 原生库无法感知连接状态 使用连接池时,池中存在失效连接,影响连接池的复用
  2. 原生库存在goroutine暴涨的风险 一个连接一个goroutine的模式,由于连接利用率低下,存在大量goroutine占用调度开销,影响性能

自研网络库 Netpoll

  1. 解决无法感知连接状态问题 引入epoll主动监听机制,感知连接状态
  2. 解决goroutine暴涨的风险 建立goroutine池,复用goroutine
  3. 提升性能 引入 NocopyBuffer,向上提供NoCopy的调用接口,编解码层面零拷贝

扩展性设计

支持多协议,也支持灵活的自定义协议扩展

img_4.png

img_5.png

性能优化

网络库优化

  1. 调度优化
    • epoll_wait 在调度上的控制
    • gopool 重用 goroutine 降低同时运行协程数
  2. LinkBuffer
    • 读写并行无锁,支持nocopy地流式读写
    • 高效扩缩容
    • NocopyBuffer池化,减少GC
  3. Pool
    • 引入内存池和对象池,减少GC开销

编解码优化

  1. Codegen
    • 预计算并分配内存,减少内存操作次数,包括内存分配和拷贝
    • Inline减少函数调用次数和避免不必要的反射操作等
    • 自研了Go语言实现的ThriftIDL 解析和代码生成器,支持完善的ThriftIDL语法和语义检查,并支持了插件机制- ThriftGo
  2. JIT
    • 使用JIT编译技术改善用户体验的同时带来更强的编解码性能,减轻用户维护生成代码的负担
    • 基于JIT编译1技术的高性能动态Thrift编解码器- Frugal

合并部署

微服务过微,传输和序列化开销越来越大

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

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

img_6.png