RPC 基本概念
远程调用函数( RPC - Remote Procedure Calls )
所谓的远程调用函数,就是本地服务通过网络,向远程的某个服务发送请求,调用某个函数。这存在以下有待解决的问题:
-
函数映射
-
数据转换成字节流
-
网络传输
RPC 概念模型如下所示,首先调用机器进行本地调用,将参数打包,通过网络传输给被调用机器。然后,被调用机器解包参数,调用函数得到计算结果,将结果打包,通过网络传输给调用机器。然后,调用机器解包结果,返回本地调用结果。
RPC 的好处
-
单一职责,有利于分工协作和运维开发
-
可扩展性强,资源使用率更优
-
故障隔离,服务的整体可靠性更高。
RPC 带来的问题
-
服务宕机,对方应该如何处理?
-
在调用过程中发生网络异常,如何保证消息的可达性?
-
请求数量突增导致服务无法及时处理,有哪些应对措施?
分层设计
RPC 分层设计大致如下所示,主要分为业务逻辑代码, IDL 文件生成的代码,编解码层,协议层,网络通信层。
生成代码
客户端、服务端同时依赖同一份 IDL ( Interface Definition Language ) 文件,该 IDL 文件可以转换生成为不同编程语言如: Golang, C++, Java.
编解码层
-
语言特定格式:许多编程语言都内建了将内存对象编码为字节序列的支持,例如 Java 有 java.io.Serializable
-
文本格式: JSON, XML, CSV 等文本格式,具有人类可读性
-
二进制编码:具备跨语言和高性能的优点。
例如 TLV 编码 - 二进制编码, Tag 表示标签,可以理解为类型 Length 表示成都 Value 值。
例如对于 Person 结构,userName 取值 Martin , favoriteNumber 取值 1337, interests 取值 { daydreaming, hacking }.
struct Person {
1: string userName,
2: i64 favoriteNumber,
3: list<string> interests
}
协议层
协议层内容的表示方式分为两类:1. 特殊结束符:一个特殊字符作为每个协议单元结束的标识。2. 变长协议:以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度。
协议的解析通常分为以下三步骤,获取 MagicNumber, 获取编码后的载体,进行解码,获取原来的载体:
关键指标
稳定性
保障策略
-
熔断:保护调用方,防止被调用的服务出现问题而影响到整个链路。
-
限流:保护被调用方,防止大流量把服务压垮。
-
超时控制:避免浪费资源在不可用节点上。
请求成功率
负载均衡、请求重试策略。
长尾请求
长尾请求指的是那些请求耗时大于所有请求耗时中99%的请求,它们的请求耗时很长,但只占一小部分。解决方案:先预设定一个阈值 t3 , 当 Req1 发送出去后 t3 时间都没有返回,则重新发送 Req2, 相当于同时有两个请求运行。然后等待请求返回,只要 Resp1 或者 Resp2 任意一个返回成功的结果,就可以立即结束这次请求。相比于等待超时后再发送请求,能大大减少整体延时。
易用性
-
开箱即用:合理的默认参数选项、丰富的文档
-
周边工具:生成代码工具、脚手架工具
观测性
-
日志、性能指标、链路追踪
-
内置观测性服务,例如:环境变量、配置、服务初始化参数、缓存信息。
高性能
目标
-
高吞吐
-
低延迟
手段
-
连接池
-
多路复用
-
高性能编解码协议
-
高性能网络库