11 如何优化RPC网络通信?

212 阅读4分钟

大家好,我是小水珠。

上一讲中,我们提高了微服务微服务框架,其中SpringCloud和Dubbo的使用最为广泛,行业内也一直存在着两者的比较,很多技术会为这两个框架哪个更好而争辩。

我记得之前我们部门在搭建微服务框架时,也是在技术选型上纠结良久,还曾一度有过激烈的讨论。当前SpringCloud炙手可热,具备完整的微服务生态,得到了很多同事的选票,但我们最终选择的确实Dubbo,这是为什么?

一 RPC通信是大型服务框架的核心

以下是基于Dubbo2.6.4版本进行的简单的性能测试。分别测试Dubbo+Protobuf序列化以及Http+Json序列化的通信性能(这里主要模拟单一TCP长连接+Protobuf序列化和短连接的Http+Json序列化的性能对比)。为了验证在数据量不同的情况下二者的性能表现,我分别准备了小对象和大对象的性能压测,通过这样的方式我们也可以间接的了解下二者在RPC通信方面的水平。

通信协议对比.jpg

二 什么是RPC通信

一提到RPC,你是否还想到MVC,SOA这些概念?如果你没有经历过这些架构的演变,这些概念就很容易混淆。你可以通过下面这张图来了解下这些架构的演变史。

RPC通信.jpg

三 RMI:JDK自带的RPC通信框架

目前RMI已经很成熟的应用在了EJB以及Spring框架中,是纯Java网络分布式应用系统的核心解决方案。RMI实现了一台虚拟机应用对远程方法的调用可以同对本地方法的调用一样,RMI帮我们封装好了其中关于远程通信的内容。

1.RMI的实现原理

我们可以通过一张图来详细地了解下整个RMI的通信过程:

RMI实现原理.jpg

2.RMI在高并发场景下的性能瓶颈

  • java默认序列化

  • TCP短连接

  • 阻塞式网络I/O

四 一个高并发场景下的RPC通信优化路径

SpringCloud的RPC通信和RMI通信的性能瓶颈非常相似。SpringCloud是基于Http通信协议(短连接)和Json序列化实现的,在高并发场景下并没有优势。那么,在瞬时高并发的场景下,我们又该如何去优化一个RPC通信呢?

RPC通信包括了建立通信,实现报文,传输协议以及传输数据编码解码等操作,接下来我们就从每一次优化出发,逐步实现整体的性能优化。

1.选择合法的通信协议

通信协议 (2).jpg

2.使用单一长连接

如果是基于TCP协议实现Socket通信,我们还能做哪些优化呢?

3.优化Socket通信

  • 实现非阻塞I/O

  • 高效的Reactor线程模型

  • 串行设计

  • 零拷贝

除了以上这些优化,我们还可以针对套接字编程提供的一些TCP参数配置项,提高网络吞吐量,Netty可以基于ChannelOption来设置这些参数。 TCP_NODELAY:TCP_NODELAY选项是用来控制是否开启Nagle算法。Nagle算法通过缓存的方式将小的数据包组装成一个大的数据包,从而避免大量的小数据包发送阻塞网络,提高网络传输的效率。我们可以关闭该算法,优化对于时延敏感的应用场景。

4.量身定做报文格式

报文格式.jpg

5.编码,解码

6.调整Linux的TCP参数设置选项

三次握手 (2).jpg

TCP参数设置.jpg

五 总结

在现在的分布式系统中,特别是系统走向微服务化的今天,服务间的通信就显得尤为频繁,掌握服务间的通信原理和通信协议优化,是你的一项必备技能。

在一些并发场景比较多的系统中,我更偏向使用dubbo实现的这一套通信协议。Dubbo协议是建立的单一长连接通信,网络I/O为NIO非阻塞读写操作,更兼容了Protobuf等性能出众的序列化框架,在高并发,小对象传输的业务中非常实用。

在企业系统中,业务往往要比普通的互联网产品复杂,服务与服务之间可能不仅仅是数据传输,还有图片以及文件的传输,所以RPC的通信协议设计需要考虑更多的功能性需求,在性能方面不追求极致。其他通信框架在功能性,生态以及易用,易入门等方面更具有优势。