深入浅出RPC框架 | 青训营笔记
这是我参与「第五届青训营 」笔记创作活动的第16天
基本概念
什么是RPC
RPC: Remote Procedure Calls远程过程调用,指的是一种通过网络从远程计算机上请求服务的协议。
RPC需要解决的问题
- 函数映射
- 数据转换成字节流
- 网络传输
RPC的模型
- User
- User-Stub
- Server
- Server-Stub
- RPC-Runtime
RPC使用
- IDL(interface description language)接口描述语言:用于描述服务接口的语言,目的在于通过规范约定远程调用,使得不同平台上运行的对象和使用不同语言的程序可以相互通信。
- 生成代码:通过编译器工具将IDL文件转换成对应的静态库
- 编解码:从内存中将数据转换成字节序列的相互过程
- 通信协议:规范了数据在网络中传输的内容和格式
- 网络传输:通常基于成熟的网络库,走TCP/UDP传输
RPC的好处
- 单一职责,有利于分工协作和运维开发
- 可拓展性强,资源利用率更优
- 故障隔离,服务整体的可靠性更高
RPC的问题
- 如何应对服务宕机的问题
- 调用过程中发生了网络异常,如何保证消息的可达性
- 请求量激增导致服务无法及时处理时,如何应对
这些都是RPC框架亟待解决的问题
分层设计
编解码层
生成代码
服务端和客户端依赖于同一份IDL文件,生成对应语言的CodeGen
数据格式
二进制编码
-
TLV编码
- Tag:标签,可以理解为类型
- Length:长度
- Value:值,Value也可以是个TLV结构
协议层
协议单元的判别
- 特殊结束符
- 变长协议
协议构造
协议解析
- 先通过MagicNumber确定协议版本、类型
- 接着确定PayloadCodec,确定编码类型
- 最后解码Payload
网络通信层
Socket API
关键指标
稳定性
保障策略
- 熔断:一个服务A调用服务B时,服务B的业务逻辑又调用了服务C,而这时服务C响应超时了,由于服务B依赖服务C,C超时直接导致B的业务逻辑一直等待,而这个时候服务A继续频繁地调用服务B,服务B就可能会因为堆积大量的请求而导致服务宕机,由此就导致了服务雪崩的问题
- 限流:当调用端发送请求过来时,服务端在执行业务逻辑之前先执行检查限流逻辑,如果发现访问量过大并且超出了限流条件,就让服务端直接降级处理或者返回给调用方一个限流异常
- 超时:当下游的服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,避免浪费资源
请求成功率
-
因为重试有放大故障的风险,首先,重试会加大直接下游的负载。如下图,假设A服务调用B服务,重试次数设置为r(包括首次请求),当B高负载时很可能调用不成动,这时A调用失败重试B,B服务的被调用量快速增大,最坏情况下可能放大到r倍,不仅不能请求成功,还可能导致B的负载继续升高,甚至直接打挂。
-
防止重试风暴,限制单点重试和限制链路重试
长尾请求
注册中间件
创建接口均采用Option模式,可以很灵活方便地注入稳定性策略
扩展性
将治理层面的逻辑封装在middleware中,这些middleware将被构造成一个有序调用序列,比如服务发现、路由、负载均衡、超时控制等,最后进入remote模块,完成远端通信
观测性
Log、Metric、Tracing
内置观测服务
字节-kitex
- 自研网络库Netpoll
- 解决无感知连接状态,引入epoll主动监听
- 解决goroutine暴涨风险
- 引入Nocopy Buffer,实现编解码层面的零拷贝
- 扩展性设计
- 网络库优化
- 编解码优化
- 合并部署
引用参考
深入浅出 RPC 框架 副本.pptx - 飞书云文档 (feishu.cn)