认识 RPC | 青训营笔记

54 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天

今天主要学习了 RPC 框架分层设计

1 什么是 RPC?

RPC:远程函数调用(RPC:Remote Procedure Calls),用于解决分布式系统中服务之间的调用问题。 通俗地讲,就是开发者能够像调用本地方法一样调用远程的服务。 所以,RPC 的作用主要体现在这两个方面:

  • 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法;
  • 隐藏底层网络通信的复杂性,让我们更专注于业务逻辑。

与之相关的概念是 "本地函数调用",接下来用这两者的不同进行深入理解 RPC

1.1 RPC 需要解决的问题

1.函数映射

在本地调用中,函数体是直接通过函数指针来指定的,我们调用哪个方法,编译器就自动调用它相应的函数指针。

但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的。所以函数都有自己的一个 ID。在所 RPC 的时候要附上这个 ID,还得有个 ID 和函数的对照关系表,通过 ID 找到对应的函数并执行。

  1. 数据转换成字节流

客户端怎么把参数值传给远程的函数呢?

在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。

  1. 网络传输

因为远程调用往往用在网络上,那如何保证在网络上高效稳定地传输数据呢?这是 RPC 需要解决的第三个问题。

以上三点也是本地函数调用和 RPC调用的区别。

1.2 RPC 的概念模型

早在1984年 Nelson 发表论文提出 RPC 过程由5个模型组成:

  • User

  • User-Stub

  • RPC-Runtime

  • Server-Stub

  • Server

2 一些相关的概念

一次 RPC 的完整过程

c23f9d916bf5ef7c121607fed59c675.png

2.1 IDL 文件

相比本地函数调用,远程调用时不知道对方用哪些方法,以及参数长什么样所以需要有一种方式来描述或者说声明我有哪些方法,方法的参数都是什么样子的,这样的话大家就能按照这个来调用,这个描述文件就是 IDL 文件。

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

2.2 生成代码

通过编译器工具(代码生成工具)把 IDL 文件转换成(不同)语言对应的静态库(lib 代码,里面封装了编解码逻辑)。

image.png

之前提到的服务双方是通过约定的规范进行远程调用,双方都依赖同一份 IDL 文件,需要通过工具来生成对应的生成文件,具体调用的时候用户代码需要依赖生成代码,所以可以把用户代码和生成代码看成一个整体。

生成代码也可以看成是编解码层的一部分。

2.3 编解码

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

image.png

2.4 通信协议

编码只是解决了跨语言的数据交换格式,但是需要制定通讯协议才可以通讯。

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

2.5 网络传输

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

3 RPC 的好处及问题

3.1 RPC 好处

  1. 单一职责。有利于分工协作和运维开发。

开发(采用不同的语言)、部署以及运维(上线独立)都是独立的。

  1. 可扩展性强,资源使用率更优。

例如压力过大的时候可以独立扩充资源,底层基础服务可以复用,节省资源。

  1. 故障隔离,服务的整体可靠性更高。

某个模块发生故障,不会影响整体的可靠性

3.2 RPC 带来的问题

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

4 分层设计

f4acb40c6e78302bc5114814e56ef5f.png

RPC 框架主要核心有三层:

image.png

4.1 编解码层

作用:把请求的数据装入字节流

IDL 中的数据格式是怎样的?

有三种数据格式:语言特定的格式、文本格式(JSON、XML、CSV)、二进制编码(Protobuf

二进制编码——具备跨语言和高性能等优点。把数据转为二进制流。举例:TLV编码

编码格式:兼容性、通用性(跨平台、跨语言)、性能(编码后数据大小和编码耗费时长)。

4.2 协议层

把编码的字节流按照约定的通信协议,添加额外的元数据,进行打包发给对方。

啥叫协议?两个知识点

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

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

框架对协议进行解析:

首先框架从内存中读取指定部分的数据(知道协议长什么样)——MagicNumber(魔法树的位置:知道用了什么协议)——PayloadCodec(知道编解码方式,用什么解码)——用 Paylaod进行解码。

4.3 网络通信层

Sockets API 的调用流程:

image.png

image.png

现实中选用封装好的网络库作为 RPC 框架的网络通信层。

选择网络库的一些指标:

提供易用 API:封装底层 Socket API\连接管理和事件分发;

功能:协议支持(TCP/UDO/UDS)、优雅退出、异常处理等;

性能:应用层 buffer 减少 copy\高性能定时器、对象池等;

RPC 框架的关键指标

稳定性

熔断、限流、超时控制

请求成功率:负载均衡、重试

长尾请求

注册中间件

易用性

开箱即用、周边工具

扩展性

框架应当提供丰富的扩展点,例如核心的传输层和协议层

观测性

Log\Metric\Tracing

内置观测性服务

高性能

高吞吐、低延迟


更多资料:

1) THeader 协议:

2)Kitex 整体架构

3)字节跳动自研网络库 Netpoll

4)字节跳动 Go RPC 框架 KiteX 性能优化实践