这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
1, 基本概念
1.1 本地和远程函数调用
- 相比本地函数调用,RPC调用需要解决的问题:函数映射;数据转换成字节流;网络传输
1.2,RPC概念
1.3,一次 RPC 的完整过程
- IDL (Interface description language)文件
IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信。(约定调用规范)
- 生成代码
通过编译器工具把IDL文件转换成语言对应的静态库。(具体调用的时候用户代码需要依赖生成代码,所以可以把用户代码和生成代码看做一个整体)
- 编解码
从内存中表示到字节序列的转换称为编码,反之为解码,也常叫做序列化和反序列化。
- 通信协议
规范了数据在网络中的传输内容和格式。除必须的请求/响应数据外,通常还会包含额外的元数据。
- 网络传输
通常基于成熟的网络库走TCP/UDP传输。
1.4, RPC 优点
- 单一职责,有利于分工协作和运维开发(开发可以采用不同语言;部署及运维都是独立的) * 可扩展性强,资源使用率更优(压力过大时可以独立扩充资源,底层基础服务可以复用,达到节省资源的目的)
- 故障隔离(一个模块发生故障,不会影响整体,服务的整体可靠性更高)
1.5 RPC带来的问题
- 服务宕机,对方应该如何处理?
- 在调用过程中发生网络异常,如何保证消息的可达性?
- 请求量突增导致服务无法及时处理,有哪些应对措施?
2.RPC 框架分层设计
2.1 分层设计
2.2编解码层
-
生成代码:依赖同一份IDL文件(同一份约束)生成不同语言的生成代码。
-
数据格式
- 1.语言特定的格式
- 2.文本格式
- 3.二进制编码
- 4.二进制编码:TLV编码 Tag:标签,可以理解为类型 Lenght:长度 Value:值,Value也可以是个TLV结构
-
选型:
-
兼容性:支持自动增加新的字段,而不影响老的服务,这将提高系统的灵活度。
-
通用性:支持跨平台、跨语言(①技术层面,序列化协议要支持跨平台、跨语言。②流行程度,可以判断此协议是否成熟,同时序列化和反序列化需要多方参与,很少人使用的协议往往意味着昂贵的学习成本。)
-
性能:从空间和时间两个维度来考虑,也就是编码后数据大小和编码耗费时长。
-
2.3 协议层
- 概念
-
特殊结束符:一个特殊字符作为每个协议单元结束的标示。(缺点:过于简单,对于一个协议单元必须要全部读入才能够进行处理,除此之外必须要防止用户传输的数据不能同结束符相同,否则就会出现紊乱。 HTTP协议头就是以回车(CR)加换行(LF)符号序列结尾。)
-
变长协议:以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度。(一般都是自定义协议,有header和payload组成,使用比较广泛)
-
协议构造:
-
协议解析
2.4 网络通信层:
-
Sockets API:介于通信层和应用层之间
-
网络库
-
提供易用API:封装底层Socket API;连接管理和事件分发
-
功能: 协议支持: tcp、 udp 和uds等;优雅退出、异常处理等
-
性能:应用层buffer减少copy;高性能定时器、对象池等
-
03,关键指标
3.1 稳定性-保障策略
- 熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路
- 限流:保护被调用方,防止大流量把服务压垮(降级处理/返回限流异常)
- 超时控制:避免浪费资源在不可用节点上(超时主动停掉不太重要的业务)
3.2稳定性-请求成功率
- 负载均街
- 重试(会加大直接下游的负载,有放大故障的风险)
- 防止重试风暴,限制单点重试和限制链路重试。
3.3稳定性-长尾请求
长尾请求一般是指明显高于均值的那部分占比较小的请求。P99 单个请求响应耗时从小到大排列,顺序处于99%位置的值即为P99值,那后面这1%就可以认为是长尾请求。在较复杂的系统中,长尾延时总是会存在。预先设定一个阈值 t3 (比超时时间小,通常建议是RPC请求延时的pct99),当Req1发出去后超过t3时间都没有返回,那我直接发起重试请求Req2,这样相当于同时有两个请求运行。然后等待请求返回,只要Resp1或者Resp2任意一个返回成功的结果, 就可以立即结束这次请求,这样整体的耗时就是t4,它表示从第一个请求发出到第一个成功结果返回之 间的时间,相比于等待超时后再发出请求,这种机制能大大减少整体延时。
3.4稳定性-注册中间件
3.5易用性
-
开箱即用: 合理的默认参数选项、丰富的文档
-
周边工具: 生成代码工具、脚手架工具
3.6扩展性
- Middleware
- Option
- 编解码层
- 协议层
- 网络传输层
- 代码生成工具插件扩展
3.7观测性
-
Log、Metric、Tracing
-
内置观测性服务
3.8 高性能
-
这里分两个维度,高性能意味着高吞吐和低延迟,两者都很重要,甚至大部分场景下低延迟更重要。
-
多路复用可以大大减少了连接带来的资源消耗,并且提升了服务端性能,我们的测试中服务端吞吐可提升30%。
-
调用端向服务端的一个节点发送请求,并发场景下,如果是非连接多路复用,每个请求都会持有一个连接, 直到请求结束连接才会被关闭或者放入连接池复用,并发量与连接数是对等的关系。而使用连接多路复用,所有请求都可以在一个连接上完成,连接资源利用上的差异明显。