假如电商系统的 QPS 已经达到了每秒 2 万次,在做了服务化拆分之后,由于我们把业务逻辑都拆分到了单独部署的服务中,那么假设你在完成一次完整的请求时需要调用 4~5 次服务,计算下来,RPC 服务需要承载大概每秒 10 万次的请求。

所以RPC框架的选型要:

1、选择合适的网络模型,有针对性地调整网络参数优化网络传输性能;

2、选择合适的序列化方式,以提升封包、解包的性能。

什么是RPC

RPC指的是通过网络调用另一台计算机上部署服务的技术。而 RPC 框架就封装了网络调用的细节,让你像调用本地服务一样调用远程部署的服务。

在引入RPC框架后会出现的问题

假设一个电商系统的商品详情页面需要商品数据、评论数据还有店铺数据。如果是一体化的项目,只需要从商品库、评论库和店铺库获取数据就可以了,不考虑缓存的情况下有三次网络请求。

但是如果独立出商品服务、评论服务和店铺服务之后,那么就需要分别调用这三个服务,而这三个服务又会分别调用各自的数据库,这就是六次网络请求。

image-20230511184337555

想要优化RPC调用,那么就要了解RPC调用的步骤都有哪些:

  • 客户端首先会将调用的类名、方法名、参数名、参数值等信息,序列化成二进制流;
  • 然后客户端将二进制流通过网络发送给服务端;
  • 服务端接收到二进制流之后将它反序列化,得到需要调用的类名、方法名、参数名和参数值,再通过动态代理的方式调用对应的方法得到返回值;
  • 服务端将返回值序列化,再通过网络发送给客户端;
  • 客户端对结果反序列化之后,就可以得到调用的结果了。

如下图:

image-20230511184610250

不难看出,想要优化RPC调用,需要从网络传输和序列化入手。

如何提升网络传输性能

在网络传输优化中,首先要做的是选择一种高性能的 I/O 模型,即我们处理I/O的方式。而单次I/O请求会分为两个节点。

首先,I/O 会经历一个等待资源的阶段,比方说,等待网络传输数据可用。这里有两种处理方式:

  • 阻塞。指的是在数据不可用时 I/O 请求一直阻塞,直到数据返回;

  • 非阻塞。指的是数据不可用时 I/O 请求立即返回,直到被通知资源可用为止。

然后是使用资源的阶段,比如说从网络上接收到数据,并且拷贝到应用程序的缓冲区里面。也有两种处理方式:

  • 同步处理。指的是 I/O 请求在读取或者写入数据时会阻塞,直到读取或者写入数据完成;

  • 异步处理。指的是 I/O 请求在读取或者写入数据时立即返回,当操作系统处理完成 I/O 请求并且将数据拷贝到用户提供的缓冲区后,再通知应用 I/O 请求执行完成。

将这两个阶段的四种处理方式做一些排列组合,再做一些补充,就得到了我们常见的五种 I/O 模型:

  • 同步阻塞 I/O;

  • 同步非阻塞 I/O;

  • 同步多路 I/O 复用;

  • 信号驱动 I/O;

  • 异步 I/O。

选择合适的序列化方式

在对网络数据传输完成调优之后,另外一个需要关注的点就是数据的序列化和反序列化。

这里要考虑序列化和反序列化的速度,以及序列化完成后的大小,因为要在网络上传输。

可以有以下几种方案:

  • JSON,性能要求不高可以选
  • Thrift 是 Facebook 开源的高性能的序列化协议
  • Protobuf 是谷歌开源的序列化协议。

如果性能要求比较高,Thrift 或者 Protobuf 都可以。

一些存储的场景下,比如说缓存中存储的数据占用空间较大,那么你可以考虑使用 Protobuf。