22毫秒级调用(RPC)

259 阅读5分钟

1.基本概念

微服务引入的新问题

  • 服务单独部署后,引入服务跨网络通信的问题
  • 拆分成多个小服务之后,服务如何治理的问题

网络通信的核心组件:RPC框架

RPC框架可以在超时方面有所限制(服务超时,服务降级,服务限流)

2.PRC

设计思路:

  • 选择合适的网络模型,有针对性地调整网络参数优化网络传输性能
  • 选择合适的序列化方式,以提升封包、解包的性能

PRC通过网络服务调用部署在另一台机器上服务的技术(下游也需要提供一个跨进程通信的端口(将服务运行在进程之上))

RMIWeb ServiceDubboGrpc
简介Java原生的远程调用框架HTTP+SOAP 协议
跨语言、跨平台
优点
缺点1.JRMP通信协议限制只能在Java语言中通信,无法跨语言通信
2.使用远程对象徐内化方式,生成的直接数组空间叫法,效率很差


拆分的越多,网络调用的次数就越多

image.png

RPC调用过程

  • 客户端将调用的类名、方法名、参数名、参数值等信息序列化成二进制流
  • 将客户端二进制流通过网络发送到服务端
  • 服务端通过序列化协议将二进制流反序列化成调用的类名,方法名,参数名和参数值,再通过动态代理方式获取计算结果
  • 服务端将返回值序列化,再通过网络发送给客户端
  • 客户端对结果反序列化后可以调用结果

image.png

提升RPC性能=网络传输+序列化

2.1如何提升网络传输性能

2.1.1选择高性能IO模型

IO模型:处理IO时的方式

一般会将IO请求分为两个阶段:

IO:I(从1号介质取数据)+O(将数据写入2号媒介)  

例如(一个网络请求会有多次IO):

  • 从网卡(硬件)将请求IO到socket中(第一次IO)
  • 将socket中的请求IO到内存中(第二次IO)
  • 将磁盘文件字节流IO到内存中(第三次IO)
  • 将内存中的字节流IO到socket中(第四次IO)
  • 将socket的字节流IO到网卡(硬件)中(第四次IO)

IO的两阶段=等待资源阶段+使用资源阶段

等待资源阶段:

处理方式=阻塞(死等数据)(数据不可用时IO一直阻塞,直到数据返回)+非阻塞(等数据通知)(数据不可用时IO请求立即返回,直到通知资源可用为止)

使用资源阶段(将接收到的请求数据拷贝到缓冲区中(内存中)):

同步处理(等处理结束)(读取和写入数据时阻塞,直到读取或者写入数据完成)+异步处理(等处理完成同志式)(读取或者写入数据时立即返回,通知应用请求执行完成)

将四种处理方式进行排列组合,得到5中IO模型

  • 同步阻塞 I/O:你站在灶台边上一直等着(等待资源)水烧开,然后倒水(使用资源)
  • 同步非阻塞 I/O:在烧水的时候躺在沙发上看会儿电视(不再时时刻刻等待资源),但是还是要时不时地去看看水开了没有,一旦水开了,马上去倒水(使用资源)
  • 同步多路 I/O 复用:同时烧好多壶水,那你就在看电视的间隙去看看哪壶水开了(等待多个资源),哪一壶开了就先倒哪一壶
  • 信号驱动 I/O:不过你发现自己总是跑厨房去看水开了没,太累了,于是你考虑给你的水壶加一个报警器(信号),只要水开了就马上去倒水
  • 异步 I/O:智能水壶,在水烧好后自动就可以把水倒好

广泛使用的是多路IO复用:select、epoll 等系统调用都是支持多路 I/O 复用模型的,Java 中的高性能网络框架 Netty 默认也是使用这种模型(Nginx)

通知监听多个请求数据,对其进行相关处理

2.1.2进行一些网络调优

tcpdump抓包用

tcp_nodelay

Nagle`s 算法

如果是连续的小数据包,大小没有一个 MSS(Maximum SegmentSize,最大分段大小),并且还没有收到之前发送的数据包的 Ack 信息,那么这些小数据包就会在发送端暂存起来,直到小数据包累积到一个 MSS,或者收到一个 Ack 为止。

DelayedACK 的超时时间默认是 40ms,所以一旦到了 40ms,接收端回给发送端 ACK,那么发送端才会发送第二个包,这样就增加了延迟。

在 Socket 上开启 tcp_nodelay ,这个参数关闭了 Nagle`s 算法,这样发送端就不需要等到上一个发送包的 ACK 返回直接发送新的数据包就好了。这对于强网络交互的场景来说非常的适用

2.2合适的序列化方法

序列化:将传输对象转换成二进制串的过程

反序列化:将二进制串转换成对象

选择序列化方法的考虑点:

  • 时间上开销
  • 空间上开销
  • 跨语言,跨平台
  • 扩展性
jsonthriftprotobuf
简介起源于 JavaScript 是一种最广泛使用的序列化协议是 Facebook 开源的高性能的序列化协议,也是一个轻量级的 RPC 框架是谷歌开源的序列化协议
特点不需要引入IDL需要引入IDL需要引入IDL
备注游戏公司
可以用于response,由客户端再反序列化一次
场景性能要求不高,宽带不大的情况下对性能有要求
有成熟的一体化方案
对性能有要求
对存储有要求的情况下

3总结

选择高性能的IO模型:同步多路IO复用模型

调整网络参数:比如将 tcp_nodelay 设置为 true

根据业务实际场景选择序列化手段:性能不高选json,否则Thrift和Portobuf选一个