RPC:RPC框架在网络通信上使用IO多路复用模型&&零拷贝技术

引入

问题:网络通信在RPC调用中起到什么作用呢?

回答:

  • RPC是解决进程间通信的一种方式。一次RPC调用,本质就是服务器消费者和服务提供者间的一次信息交换的过程。
  • 服务调用者通过网络IO发送一条请求消息,服务提供者接收并解析,处理完相关的业务逻辑之后,再发送一条响应消息给服务调用者,服务调用者接收并解析响应消息,处理完相关的响应逻辑,一次RPC调用就结束了
  • 可以说,网络通信是整个RPC调用流程的基础

总结:RPC是用来解决两个应用之间的通信的,而网络是两台机器之间的“桥梁”,只有架好了桥梁,我们才能把请求数据从一端传输到另一端。关于网络通信,只要记住一个关键词就行了——可靠的传输

RPC调用在大多数情况下,是一个高并发调用的场景,因此倾向于使用IO多路复用模型。开发语言的网络通信框架的选项上,我们最优的选择是基于reactor模型实现的框架,比如java选择netty

零拷贝

  • 零拷贝是系统层面上的零拷贝,主要目标是避免用户空间和内核空间之间的数据拷贝操作,可以提升CPU的利用率
  • 而netty的零拷贝则不太一样,它完全站在了用户空间上,其拷贝技术主要是偏向于数据操作的优化上

那么 Netty 这么做的意义是什么呢?

  • 在网络传输过程中,RPC并不会把请求参数的所有二进制数据整体一下子发送到对端机器上,中间可能会拆分成好几个数据包,也可能会合并其他请求的数据包,所以消息都需要有边界。一端的机器收到消息之后,就需要对数据包进行处理,根据边界对数据包进行分隔和合并,最终获得一条完整的消息
  • 那收到消息后,对数据包的分隔和合并,是在用户空间完成的,还是在内核空间完成的呢?
  • 当然是在用户空间,因为对数据包的处理工作都是由应用程序来处理的,那么这里有没有可能存在数据的拷贝操作?可能会存在,当然不是在用户空间和内核空间之间的拷贝,是用户空间内部内存中的拷贝处理操作。Netty 的零拷贝就是为了解决这个问题,在用户空间对数据操作进行优化。

那么 Netty 是怎么对数据操作进行优化的呢?

  • netty提供了CompositeByteBuf类,它可以将多个ByteBuf合并为一个逻辑上的ByteBuf,避免了各个ByteBuf之间的拷贝
  • ByteBuf支持slice操作,因此可以将ByteBuf分解为多个共享同一个存储区域的ByteBuf,避免了内存的拷贝
  • 通过wrap操作,我们可以将byte[]数组,ByteBuf、ByteBuffer 等包装成一个 NettyByteBuf 对象, 进而避免拷贝操作。

Netty 框架中很多内部的 ChannelHandler 实现类,都是通过CompositeByteBuf、 slice、wrap 操作来处理 TCP 传输中的拆包与粘包问题的。

那么 Netty 有没有解决用户空间与内核空间之间的数据拷贝问题的方法呢?

  • Netty 的 ByteBuffer 可以采用 Direct Buffers,使用堆外直接内存进行 Socketd 的读写操作,最终的效果虚拟内存所实现的效果是一样的。
  • Netty 还提供 FileRegion 中包装 NIO 的 FileChannel.transferTo() 方法实现了零拷贝,这与 Linux 中的 sendfile 方式在原理上也是一样的。

小结

零拷贝的好处是避免了没必要的CPU拷贝,让CPU解脱出来去做其他的事,同时也减少了CPU在内核空间和用户空间之间的上下文切换,从而提升了网络通信效率和应用程序整体的性能

而 Netty 的零拷贝与操作系统的零拷贝是有些区别的,Netty的零拷贝倾向于用户空间中对数据操作的优化,这对处理TCP传输中的拆包粘包问题有着重要的意义,对应用程序处理请求数据和返回数据也有重要意义

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值