这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
一次完整的RPC调用
IDL (lnterface description language)文件
IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信
生成代码
通过编译器工具把IDL文件转换成语言对应的静态库
编解码
从内存中表示到字节序列的转换称为编码,反之为解码,也常叫做序列化和反序列化
通信协议
规范了数据在网络中的传输内容和格式。除必须的请求/响应数据外,通常还会包含额外的元数据
网络传输
通常基于成熟的网络库走TCP/UDP传输
分层设计
以Apache Thrift为例
编解码层
生成代码
生成什么代码?
接口中对应的请求和响应代码
数据格式
- 编程语言内建了将内存对象编码为字节序列的支持,如java.io.Serializable
- 文本格式如json,xml,csv
- 二进制编码如Thrift的BinaryProtocol,Protobuf
选型
- √兼容性
- 支持自动增加新的字段,而不影响老的服务,这将提高系统的灵 活度
- √通用性
- 支持跨平台、跨语言
- √性能
- 从空间和时间两个维度来考虑,也就是编码后数据大小和编码耗费时长
协议层
- 特殊结束符
- 一个特殊字符作为每个协议单元结束的标示
- 变长协议
- 以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度
- 以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度
协议构造
LENGTH:数据包大小,不包含自身
HEADER MAGIC:标识版本信息,协议解析时候快速校验
SEQUENCE NUMBER:表示数据包的seqID,可用于多路复用,单连接内递增
HEADER SIZE:头部长度,从第14个字节开始计算一直到PAYLOAD前
PROTOCOL ID:编解码方式,有Binary和Compact 两种
TRANSFORM ID:压缩方式,如zlib 和snappy
INFO D:传递—些定制的meta 信息
PAYLOAD:消息体
网络通信层
Socket API
服务端
- 创建一个监听套接字 socket()
- 设置套接字属性(可以设置,也可以忽略) setsockopt()
- 初始化地址结构体(协议簇,端口号,服务器ip地址)
- 绑定地址结构体 bind()
- 开启监听 listen()
- 接收连接请求accept(),建立连接(得到通信套接字)
- 数据收发 收recv/read 发send/write
- 关闭连接socket套接字 close(), shutdown()
客户端
- 创建一个通信套接字 socket()
- 设置套接字属性(可以设置,也可以忽略) setsockopt()
- 初始化地址结构体(协议簇,端口号,设置服务器的ip地址)
- 请求连接 connect()
- 数据收发 收recv/read 发send/write
- 关闭连接socket套接字 close(), shutdown()
RPC关键指标
稳定性
保障策略
熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路
限流:保护被调用方.防止大流量把服务压垮
超时控制:避免浪费资源在不可用节点上
请求成功率
负载均衡,重试
长尾请求
长尾请求一般是指明显高于均值的那部分占比较小的请求。
如何提高长尾请求的请求成功率?
Backup Request
注册中间件
拓展性
中间件, 参数, 编解码层, 协议层, 网络传输层, 代码生成工具插件扩展
观测性
日志,监控面板,链路跟踪(如每个服务耗时多少,性能如何)
高性能——高吞吐,低延迟
连接池,多路复用,高性能编解码协议,高性能网络库