Netty必知必会(一)—— 零拷贝技术

一、什么是零拷贝?(OS层面、用户态和内核态)

9.1 什么是零拷贝? | 小林coding (xiaolincoding.com)

1.传统的文件传输

2.mmap + write 实现零拷贝

mmap() 系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间。

3.sendfile 实现零拷贝

Linux 内核版本必须要 2.1 以上的版本,sendfile() 可以替代前面的 read() 和 write() 这两个系统调用。

4.SG-DMA 实现零拷贝

如果网卡支持SG-DMA技术,网卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷贝到网卡的缓冲区里。

二、Netty中的零拷贝?(Java层面、用户态)

1.通过堆外内存实现零拷贝

深入netty10-堆外内存_netty堆外内存限制 jvm命令-CSDN博客

直接内存也称为堆外内存,也就是不受JVM控制的内存。

Netty 的接收和发送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接内存进行 Socket 读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行 Socket 读写,JVM 会将堆内存 Buffer 拷贝一份到直接内存中,然后才写入 Socket 中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。

2.通过组合数据实现零拷贝

Netty 允许我们将多段数据合并为一整段虚拟数据供用户使用,而过程中不需要对数据进行拷贝操作。

1.1  TCP 粘包 / 分包 的问题

在 stream-based transport(如 TCP/IP)的传输过程中,数据包有可能会被重新封装在不同的数据包中,例如当你发送如下数据时:

Data Stream Sent

有可能实际收到的数据如下:

Data Stream Received

因此在实际应用中,很有可能一条完整的消息被分割为多个数据包进行网络传输,而单个的数据包对你而言是没有意义的,只有当这些数据包组成一条完整的消息时你才能做出正确的处理,而 Netty 可以通过零拷贝的方式将这些数据包组合成一条完整的消息供你来使用。而此时,零拷贝的作用范围仅在用户空间中。

1.2  通过 CompositeByteBuf

Netty 提供了 CompositeByteBuf 类, 它可以将多个 ByteBuf 合并为一个逻辑上的 ByteBuf, 避免了各个 ByteBuf 之间的拷贝。

1.3  通过 wrap 操作实现零拷贝

通过 wrap 操作, 我们可以将 byte[] 数组、ByteBuf、ByteBuffer等包装成一个 Netty ByteBuf 对象, 进而避免了拷贝操作。

1.4  通过 slice 操作实现零拷贝

ByteBuf 支持 slice 操作, 因此可以将 ByteBuf 分解为多个共享同一个存储区域的 ByteBuf, 避免了内存的拷贝。

3.通过 FileRegion 实现零拷贝

通过 FileRegion 包装的FileChannel.tranferTo 实现文件传输, 可以直接将文件缓冲区的数据发送到目标 Channel, 避免了传统通过循环 write 方式导致的内存拷贝问题。

如果 Linux 系统⽀持 sendfile() 系统调⽤,那么 transferTo() 实际上最后就会使⽤到 sendfile() 系统调
⽤函数。

上述详细讲解都在下面这个链接里,一定要看哦!

 java - 对于 Netty ByteBuf 的零拷贝(Zero Copy) 的理解 - 后台开发 - SegmentFault 思否

三、传输文件应该注意什么?

把磁盘⽂件数据拷⻉「内核缓冲区」⾥,这个「内核缓冲区」实际上是 磁盘⾼速缓存( PageCache
PageCache 的优点主要是两个:
  • 缓存最近被访问的数据;
  • 预读功能;
但是,在传输⼤⽂件( GB 级别的⽂件)的时候, PageCache 会不起作⽤, 这是因为如果你有很多 GB 级别⽂件需要传输,每当⽤户访问这些⼤⽂件的时候,内核就会把它们载⼊ PageCache 中,于是 PageCache 空间很快被这些⼤⽂件占满。
会带来 2 个问题:
  • PageCache 由于⻓时间被⼤⽂件占据,其他「热点」的⼩⽂件可能就⽆法充分使⽤到 PageCache于是这样磁盘读写的性能就会下降了;
  • PageCache 中的⼤⽂件数据,由于没有享受到缓存带来的好处,但却耗费 DMA 多拷⻉到 PageCache ⼀次
所以,传输⽂件的时候,我们要根据⽂件的⼤⼩来使⽤不同的⽅式:
  • 传输⼤⽂件的时候,使⽤「异步 I/O + 直接 I/O」;
  • 传输⼩⽂件的时候,则使⽤「零拷⻉技术」;
异步 I/O 并没有涉及到 PageCache ,所以使⽤异步 I/O 就意味着要绕开 PageCache。
绕开 PageCache I/O 叫直接 I/O ,使⽤ PageCache I/O 则叫缓存 I/O 。通常,对于磁盘,异步 I/O 只 ⽀持直接 I/O

四、参考

一文读懂网络框架Netty_文化 & 方法_蔡昱星_InfoQ精选文章

Netty系列之Netty高性能之道_后端_李林锋_InfoQ精选文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值