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

49 阅读2分钟

RPC

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

基本概念

本地函数调用

func main(){
    var a = 2
    var b = 3
    res:=calculate(a,b)
    fmt.Println(res)
    return
}
func calculate(x,y int){
    z:=x*y
    return z
}

远程函数调用(RPC-Remote Procedure Calls)
问题:函数映射、数据转换成字节流、网络传输

概念模型

image.png User、User_stub、RPC_Runtime、Server-Stub、Server

完整过程

概念:

  • IDL:中立的描述接口语言
  • 生成代码:编译器把IDL转换成对应语言静态库
  • 编解码:从内存中表示到字节序列的转换称为编码
  • 通信协议:规范了数据在网络中的传输内容和格式
  • 网络传输:基于TCP/UDP 好处:
  • 单一职责,有利于分工和运维
  • 可扩展性强
  • 故障隔离,服务整体性能高 问题:
  • 服务宕机
  • 网络异常
  • 请求量突增

分层设计

image.png

编解码

数据格式

分类:

  • 语言特定:兼容性不好
  • 文本格式:人类可读性
  • 二进制编码:跨语言、高性能 TLV编码:
  • Tag:标签(类型)
  • Length:长度
  • Value:值(也可是TLV结构) 例子:
struct Person{
    1: required string            userName,
    2: optional i64                  favoriteNumber,
    3: optional list<string> interests
}

选型

  • 兼容性
  • 通用型
  • 性能

协议

概念:

  • 特殊结束符:特殊字符作为消息结束标示
  • 变长协议:定长部分描述不定长的内容长度

协议构造:

image.png

协议解析:

MagicNumber->PayloadCodec->Payload

网络通信

Socket API

image.png

网络库

  • 提供易用API:封装socket API、连接管理和事件分发
  • 功能:tcp/udp/uds等、优雅退出、异常处理
  • 性能:应用层buffer、高性能定时器、对象池

关键指标

  • 稳定性
    • 熔断、限流、超时控制
    • 负载均衡、重试
    • 备份请求
    • 注册中间件
  • 易用性
    • 开箱即用
    • 周边工具(脚手架、生成代码工具)
  • 扩展性
    • Middleware
    • Option
    • 编解码层
    • 协议层
    • 网络传输层
    • 代码生辰工具
  • 观测性
    • Log、Metric、Tracing
    • 内置观测性服务
  • 高性能
    • 链接池、多路复用、高性能编解码协议、高性能网络库

实践

kitex

image.png

Netpoll

  • 解决无法感知连接状态问题
  • 解决goroutine暴涨问题
  • 提升性能
    • 调度优化:epoll_wait、gopool
    • LinkBuffer:读写并行锁、高效扩缩容、Nocopy Buffer池化
    • Pool:引入内存池和对象池
    • Codegen:预计算分配内存
    • JIT:提升编解码性能

合并部署

微服务过微,传输和序列化开销大,将亲和性强的服务实例尽可能调度到同一个物理机,远程RPC调用优化为本地IPC调用