RPC 入门

笔者参加了今年字节跳动举办的后端青训营,在听了其中一节关于RPC入门介绍的课后,作下本篇笔记。

本篇笔记,主要讲述了RPC的基本概念,以及讲述RPC分层设计中的3个核心层次,围绕RPC的关键指标构建一个健壮的RPC框架。

 

基本概念

本地函数调用

以下面的代码为例:

func main() {
   var a = 2
   var b = 3
   result := calculate(a, b)
   fmt.Println(result)
   return
}

func calculate (x, y int) int {
   z := x * y
   return z
}

本地函数调用的过程为:

  1. 将a和b的值压栈
  2. 通过函数指针找到calculate函数,进入函数取出栈中的值2和3,将其赋予×和y
  3. 计算x*y,并将结果存在z
  4. 将z的值压栈,然后从calculate返回
  5. 从栈中取出z返回值,并赋值给result

远程函数调用

RPC:Remote Procedure Calls

以网上商城购物为例:

image.png

在网上商城购物后,需要调用远程的支付服务,支付服务再返回扣款的结果,这个调用与本地调用区别就在于中间是隔了一个网络的,在不同机器上。

RPC需要解决的问题:

  1. 函数映射:在本地调用时,函数体是通过函数指针直接指定,但是在远程调用中,调用是发生在两个不同的进程上,进程的地址空间不同,因此要给每个函数分配id,解决函数id的对应关系,如何通过
  2. 数据转换成字节流:在本地调用时,数据直接通过压栈和出栈即可完成数据的传递,而在远程调用中,调用发生在两个不同机器上的进程,不能通过内存传递参数,因此需要客户端先把数据转换成字节流传给服务端,服务端再把字节流转换为能识别的数据
  3. 网络传输:远程调用是发生在网络上的,需要保证网络传输的高效稳定

RPC概念模型

1984年 Nelson发表了论文《Implementing Remote Procedure Calls》,其中提出了RPC的过程由5个模型组成: User、User-Stub、RPC-Runtime、Server-Stub、Server

image.png

一次RPC的完整过程

IDL (Interface description language)文件

IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信

生成代码

通过编译器工具把IDL文件转换成语言对应的静态库

编解码

从内存中表示到字节序列的转换称为编码,反之为解码,也常叫做序列化和反序列化

通信协议

规范了数据在网络中的传输内容和格式。除必须的请求/响应数据外,通常还会包含额外的元数据

网络传输

通常基于成熟的网络库走TCP/UDP传输

image.png

RPC的好处

  1. 单一职责,有利于分工协作和运维开发
  2. 可扩展性强,资源使用率更优
  3. 故障隔离,服务的整体可靠性更高

RPC存在的问题

  1. 服务宕机,对方应该如何处理?
  2. 在调用过程中发生网络异常,如何保证消息的可达性?
  3. 请求量突增导致服务无法及时处理,有哪些应对措施?

小结

  1. 本地函数调用和 RPC 调用的区别:函数映射、数据转成字节流、网络传输
  2. RPC 的概念模型:User、User-Stub、RPC-Runtime、Server-Stub、Server
  3. 一次 RPC 的完整过程,并讲解了 RPC 的基本概念定义
  4. RPC 带来好处的同时也带来了不少新的问题,将由RPC框架来解决

 

分层设计

分层设计 - 以 Apache Thrift 为例

image.png

编解码层

生成代码

image.png

数据格式

  • 语言特定的格式:许多编程语言都内建了将内存对象编码为字节序列的支持,例如Java有 java.io.Serializable
  • 文本格式:JSON、XML、CSV等文本格式,具有人类可读性
  • 二进制编码:具备跨语言和高性能等优点,常见有Thrift的 BinaryProtocol,Protobuf 等

二进制编码

TLV编码:

  • Tag: 标签,可以理解为类型
  • Length: 长度
  • Value: 值,Value也可以是个TLV结构

image.png

上面代码的编码结果:

image.png

TLV编码结构简单清晰,并且扩展性较好,但是由于增加了Tag和Length两个冗余信息,有额外的内存开销,特别是在大部分字段都是基本类类的情况下有不小的空间浪费

选型

  • 兼容性:支持自动增加新的字段,而不影响老的服务,这将提高系统的灵活度
  • 通用性:支持跨平台、跨语言
  • 性能:从空间和时间两个维度来考虑,也就是编码后数据大小和编码耗费时长

协议层

概念

  • 特殊结束符:一个特殊字符作为每个协议单元结束的标示

image.png

  • 变长协议:以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度

image.png

协议构造 - 以 Apache Thrift 中的协议为例

image.png

LENGTH: 数据包大小,不包含自身
HEADER MAGIC: 标识版本信息,协议解析时候快速校验
SEQUENCE NUMBER: 表示数据包的seqID,可用于多路复用,单连接内递增
HEADER SIZE: 头部长度,从第14个字节开始计算一直到PAYLOAD前
PROTOCOL ID: 编解码方式,有Binary和Compact两种
TRANSFORM ID: 压缩方式,如zlib和snappy
INFO ID: 传递一些定制的meta信息
PAYLOAD: 消息体

协议解析

image.png

网络通信层

Sockets API

image.png

image.png

网络库

  • 提供易用API:封装底层Socket API连接管理和事件分发
  • 功能:协议支持: tcp、udp 和uds等优雅退出、异常处理等
  • 性能:应用层 buffer减少copy高性能定时器、对象池等

小结

  1. RPC框架主要核心有三层: 编解码层、协议层和网络通信层
  2. 二进制编解码的实现原理和选型要点
  3. 协议的一般构造,以及框架协议解析的基本流程
  4. 网络库的基本架构,以及选型时要考察的核心指标

 

关键指标

稳定性

保障策略

  • 熔断: 保护调用方,防止被调用的服务出现问题而影响到整个链路
  • 限流: 保护被调用方.防止大流量把服务压垮
  • 超时控制: 避免浪费资源在不可用节点上

以上三点都可以归为降级

image.png

请求成功率

  • 负载均衡:

image.png

  • 重试:

image.png

长尾请求

长尾请求一般是指明显高于均值的那部分占比较小的请求。

业界关于延迟有一个常用的P99标准, P99单个请求响应耗时从小到大排列,顺序处于99%位置的值即为P99值,那后面这1%就可以认为是长尾请求。

在较复杂的系统中,长尾延时总是会存在。造成这个的原因非常多,常见的有网络抖动,GC,系统调度。

我们预先设定一个阈值t3(比超时时间小,通常建议是 RPC 请求延时的 99% ),当 Req1 发出去后超过 t3 时间都没有返回,那我们直接发起重试请求 Req2,这样相当于同时有两个请求运行。然后等待请求返回,只要 Resp1 或者 Resp2 任意一个返回成功的结果,就可以立即结束这次请求,这样整体的耗时就是 t4 ,它表示从第一个请求发出到第一个成功结果返回之间的时间,相比于等待超时后再发出请求,这种机制能大大减少整体延时。

image.png

注册中间件

image.png

易用性

  • 开箱即用:合理的默认参数选项、丰富的文档
  • 周边工具:生成代码工具、脚手架工具

扩展性

一次请求发起首先会经过治理层面,治理相关的逻辑被封装在middleware中,这些middleware会被构造成一个有序调用链逐个执行,比如服务发现、路由、负载均衡、超时控制等,mw执行后就会进入到remote模块,完成与远端的通信

image.png

观测性

image.png

  • Log:日志
  • Metric:监控,通过面板看服务的QPS、延迟等信息
  • Tracing:链式跟踪,可以观察每个阶段的耗时多少,以此排查耗时原因

高性能

高性能分两个维度:高吞吐和低延迟

image.png

多路复用可以大大减少了连接带来的资源消耗,并且提升了服务端性能,测试中服务端吞吐可提升30%。

调用端向服务端的一个节点发送请求,并发场景下,如果是非连接多路复用,每个请求都会持有一个连接,直到请求结束连接才会被关闭或者放入连接池复用,并发量与连接数是对等的关系。而使用连接多路复用,所有请求都可以在一个连接上完成,连接资源利用上的结果差异明显。

小结

  1. 框架通过中间件来注入各种服务治理策略,保障服务的稳定性
  2. 通过提供合理的默认配置和方便的命令行工具可以提升框架的易用性
  3. 框架应当提供丰富的扩展点,例如核心的传输层和协议层
  4. 观测性除了传统的Log、Metric和Tracing之外,内置状态暴露服务也很有必要
  5. 性能可以从多个层面去优化,例如选择高性能的编解码协议和网络库

 

企业实践

有空再补充吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值