Netty的零拷贝

技术主题

netty本质上就是一款优秀的网络编程框架,凭借自己基于NIO编程,零拷贝等技术细节,

技术原理

零拷贝机制(zero-copy)是在操作数据时不需要将数据从一块内存复制到另一块内存区域的技术,这样就避免了内存的拷贝,使的可以提高CPU的利用率。零拷贝机制是一种操作数据的优化方案,通过避免数据在内存中拷贝达到的提高cpu性能的方案。

一Netty实现零拷贝的两种方式

Direct Memory Buffer

当需要传输数据时,Netty会把发送的数据先读入Direct Memory Buffer中,然后通过底层的操作系统调用将Direct Memory Buffer中的内容直接发送到网络中。这样就避免了数据从java堆内存复制到操作系统的内核缓存的步骤。这样可以避免两个缓冲区之间必要的数据拷贝,减少了cpu占用和内存带宽,加快传输速度。

FileChannel.transferTo()

如果需要传输的数据是一个文件,Netty使用FileChannel.transferTo()方法实现零拷贝

二操作系统的零拷贝机制

操作系统的存储空间包含硬盘和内存,而内存又分成用户空间和内核空间,以从文件服务器下载文件为例,服务器需要将硬盘中的数据通过网络通信发送给客户端,大致流程如下:
第一步:操作系统通过DMA传输将硬盘中的数据复制到内核缓冲区
第二步:操作系统执行read方法将内核缓冲区的数据复制到用户空间
第三步:操作系统执行write方法将用户空间的数据复制到内核socket缓冲区
第四步:操作系统通过DMA传输将内核socket缓冲区数据复制给网卡发送数据
流程如下图示:

Netty的零拷贝_第1张图片
整个流程中:DMA拷贝2次、CPU拷贝2次、用户空间和内核空间切换4次
操作系统为了减少CPU拷贝数据带来的性能消耗,提供几种解决方案来减少CPU的拷贝次数

2.1使用mmap函数

mmap函数的作用相当于内存共享,将内核空间的内存区域和用户空间共享,这样就避免了将内核空间的数据拷贝到用户空间的步骤。

2.2使用sendfile函数

senfile函数的作用是将一个文件描述符的内容发送给另一个文件描述符。而用户空间是不需要关心文件描述符的,所以整个的拷贝过程只会在内核空间操作,相当于减少了内核空间和用户空间之间数据的拷贝过程,而且还避免了CPU在内核空间和用户空间之间的来回切换过程

三Java中的零拷贝机制

1、Java的应用程序经常会遇到数据传输的场景,在javaNIO包中就提供了零拷贝机制的实现,主要是通过NIO包中的FileChannel提供了transferTo和transferFrom方法,都是调用了底层操作系统的sendfile函数来实现的CPU零拷贝机制
2、kafka服务器就是采用了FileChannel的transfer方法实现了高性能的IO传输操作。
3、Netty中的零拷贝机制netty作为nio的高性能网络通信框架,同样也实现了零拷贝机制,不过和操作系统的零拷贝机制则不是一个概念。

Netty中的零拷贝机制体现多个场景:
1)使用直接内存,在进行IO数据传输时避免了ByteBuf从堆外内存拷贝到堆内内存的步骤,而如果使用堆内内存分配ByteBuf的话,那么发送数据时需要将IO数据从堆内内存拷贝到堆外内存才能通过Socket发送
2)Netty的文件传输使用了FileChannel的transferTo方法,底层使用到sendfile函数来实现了CPU的零拷贝
3)Netty中提供CompositeByteBuf类,用于将多个ByteBuf合并成逻辑上的ByteBuf,避免了将多个ByteBuf拷贝成一个ByteBuf的过程
4)ByteBuf支持slice方法可以将ByteBuf分解成多个共享内存区域的ByteBuf,避免了内存拷贝。

你可能感兴趣的:(netty学习,网络,服务器,java)