概念
RPC - Remote Procedure Calls 远程函数调用
- 挑战
- 函数映射
- 远程设备上进程与请求进程地址空间不一致,通常通过函数ID来确定调用的函数
- 数据转换为字节流
- 序列化
- 网络传输
- 结构
- User
- User-Stub
- RPC-Runtime
- Server-Stub
- Server
- 一次RPC的流程
- IDL文件(Interface description language)
- IDL通过中立的方式描述接口
- 不同平台/语言上运行的对象可以相互通信
- 生成代码
- 借助编译器将IDL文件转成语言对应的静态库
- 编解码
- 序列化与反序列化
- 通信协议
- 数据传输的格式和内容,包括额外的元数据
- 网络传输
- 通常基于成熟网络库,走TCP/UDP
- IDL文件(Interface description language)
- RPC优点
- 单一职责,利于分工和运维
- 可扩展性强,资源使用率高
- 故障隔离
- 挑战
- 服务宕机,请求方如何应对
- 调用过程中网络异常,保证消息可达
- 请求量突增加,服务无法及时处理如何应对
分层设计
- 编解码层
- 将IDL文件转换成不同语言对应的lib代码
- 编解码
- 数据格式
- 语言特定
- 文本格式json,xml,csv
- 二进制编码Protobuf等
- 选型
- 兼容、通用、性能
- 数据格式
- 协议层
- 结束符
- 特殊结束符:e.g. \r\n
- 变长协议:Length + message
- 结束符
- 网络通信层
- 提供易用的API
- 封装socketAPI
- 连接管理和事件分发
- 功能
- 协议支持
- 优雅退出、异常处理
- 性能
- 应用层buffer减少copy
- 高性能定时器、对象池等
- 提供易用的API
关键指标
- 稳定性
- 保障策略
- 熔断、限流、超时控制
- 请求成功率
- 复杂均衡、重试
- 长尾请求
- Backup Request
- 注册中间件
- 保障策略
- 易用性
- 开箱即用
- 周边工具
- 扩展性
- 观测性
- 高性能
Kitex示例
- 整体架构
- 核心组件
- 与公司内部基础设施集成
- 代码生成工具
- 网络库
- 引入epoll主动监听机制,感知连接状态
- 建立goroutine池,服用goroutine
- 引入Noccpy buffer,编/解码层面零拷贝
- 扩展设计
- 支持多协议和灵活自定义协议扩展
- 性能优化
- 调度设计
- Epoll_wait在调度上控制
- 重用goroutinue
- LinkBuffer
- 读写并行无锁
- nocpy流式读写
- 高效扩缩容
- Nocopy BUffer池化,减少GC压力
- Pool
- 对象池、内存池
- 编解码优化
- Codegen
- 预分配内存
- Inline减少函数调用和不必要反射
- JIT
- just-in-time compilication即编译延迟到代码第一次运行时
- 合并部署
- 微服务过微,传输和序列化开销会很大
- 将亲和性强的服务实例调度到同一个物理机,将远程RPC调用优化为本地IPC调用
- Codegen
- 调度设计
这里主要是一些关于RPC框架的设计需求和性能优化,其优化涉及到从用户层到网络层,还涉及了扩展和部署优化等,总结了一个高性能RPC框架设计的思路,不过这个显然也必须业务量和代码量都到了一定规模才有意义