什么是零拷贝, 从 Java 到 Netty

简介: 什么是零拷贝, 从 Java 到 Netty

前言

零拷贝是老生常谈的话题了, 不管是Kafka还是Netty都用到了零拷贝的知识, 本篇着重讲解了什么是零拷贝, 同时在JavaNetty中分别是怎么实现零拷贝的

什么是零拷贝

零拷贝是指计算机在执行IO操作的时候, CPU不需要将数据从一个存储区复制到另一个存储区, 进而减少上下文切换以及 CPU 拷贝的时间, 这是一种IO操作优化技术

零拷贝不是没有拷贝数据, 而是减少用户态, 内核态的切换次数 和 CPU拷贝次数, 目前实现零拷贝的主要三种方式分别是:

  • mmap + write
  • sendfile
  • 带有DMA收集拷贝功能的 sendfile

mmap

虚拟内存把内核空间和用户空间的虚拟地址映射到同一个物理地址, 从而减少数据拷贝次数, mmap技术就是利用了虚拟内存的这个特点, 它将内核中的读缓冲区与用户空间的缓冲区进行映射, 所有的IO操作都在内核中完成

sendfile

sendfileLinux 2.1 版本之后内核引入的一个系统调用函数

sendfile表示在两个文件描述符之间传输数据, 他是在操作系统内核中完成的, 避免了数据从内核缓冲区和用户缓冲区之间的拷贝操作, 因此可以用其来实现零拷贝

Linux 2.4版本之后, 对sendfile进行了升级, 引入了SG-DMA技术, 可以直接从缓冲区中将数据读取到网卡, 这样的话可以省去CPU拷贝

Java 实现的零拷贝

mmap

Java NIO有一个ByteBuffer的子类MappedByteBuffer, 这个类采用direct buffer也就是内存映射的方式读写文件内容. 这种方式直接调用系统底层的缓存, 没有JVM和系统之间的复制操作, 主要用户操作大文件

sendfile

FileChanneltransferTo()方法或者transferFrom()方法,底层就是sendfile() 系统调用函数。 实现了数据直接从内核的读缓冲区传输到套接字缓冲区, 避免了用户态与内核态之间的数据拷贝

Kafka 就是使用到它

Netty 的零拷贝

Netty的哦零拷贝主要体现在以下几个方面

  • slice
  • duplicate
  • CompositeByteBuf
  • ....

我们主要讲一下slice, 其他的下次一定

log 工具类

import io.netty.buffer.ByteBuf;
import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
import static io.netty.util.internal.StringUtil.NEWLINE;
public class ByteBufUtil {
    // 打印
    public static void log(ByteBuf buf){
        final int length = buf.readableBytes();
        int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
        StringBuilder str = new StringBuilder(rows * 80 * 2)
                .append("read index:").append(buf.readerIndex())
                .append(" write index: ").append(buf.writerIndex())
                .append(" capacity:").append(buf.capacity())
                .append(NEWLINE);
        appendPrettyHexDump(str, buf);
        System.out.println(str.toString());
    }
}
复制代码

slice

对原始的ByteBuf进行切片成多个ByteBuf, 切片后的ByteBuf并没有发生内存复制, 还是使用原始的ByteBuf内存, 但是切片后的ByteBuf各自有独立的read, write指针

注意:

  • slice不允许更改切片的容量, 切片时设置的长度是多少就是多少, 不允许扩容
  • 当我们释放原始ByteBuf内存之后, 切片后的ByteBuf就不能再访问了

测试:

  • 首先创建一个ByteBuf, 然后对其进行切片
  • 更改某一个切片查看原始ByteBuf是否更改
  • 原始数据跟着更改了说明内存地址没有发生改变

测试类

public static void main(String[] args) {
    // 创建 ByteBuf
    ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(10);
    // 向 byteBuf 缓冲区写入数据
    StringBuilder str = new StringBuilder();
    for (int i = 0; i < 5; i++) {
        str.append("nx");
    }
    byteBuf.writeBytes(str.toString().getBytes());
    // 打印当前 byteBug
    ByteBufUtil.log(byteBuf);
    // 切片的过程中并没有发生数据复制
    final ByteBuf slice = byteBuf.slice(0, 5);
    final ByteBuf slice1 = byteBuf.slice(5, 5);
    // 打印第一个切片
    ByteBufUtil.log(slice);
    // 打印第二个切片
    ByteBufUtil.log(byteBuf);
    slice.setByte(0, 'a');
    System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
    // 打印第一个切片
    ByteBufUtil.log(slice);
    // 打印原始数组
    ByteBufUtil.log(byteBuf);
}
复制代码

打印结果如下

网络异常,图片无法展示
|




目录
相关文章
|
13天前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
|
3月前
|
微服务
成功解决:java.lang.NoSuchMethodError: reactor.netty.http.client.HttpClient.chunkedTransfer(Z)Lreactor/ne
这篇文章讲述了在微服务架构中整合gateway网关时遇到的`java.lang.NoSuchMethodError`错误的解决方法。问题主要是由于`spring-boot-starter-parent`的版本和`spring-cloud-starter-gateway`的版本不匹配所导致。文章提供了具体的版本不一致的错误配置,并给出了匹配的版本配置方案,以及成功测试的截图。
成功解决:java.lang.NoSuchMethodError: reactor.netty.http.client.HttpClient.chunkedTransfer(Z)Lreactor/ne
|
3月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
115 0
|
3月前
|
Java 应用服务中间件 Linux
(九)Java网络编程无冕之王-这回把大名鼎鼎的Netty框架一网打尽!
现如今的开发环境中,分布式/微服务架构大行其道,而分布式/微服务的根基在于网络编程,而Netty恰恰是Java网络编程领域的无冕之王。Netty这个框架相信大家定然听说过,其在Java网络编程中的地位,好比JavaEE中的Spring。
130 3
|
3月前
|
存储 网络协议 Java
【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!
【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。
70 0
|
5月前
|
监控 网络协议 Java
Java一分钟之-Netty:高性能异步网络库
【6月更文挑战第11天】Netty是Java的高性能异步网络框架,基于NIO,以其高吞吐量、低延迟、灵活性和安全性受到青睐。常见问题包括内存泄漏、ChannelHandler滥用和异常处理不当。要规避这些问题,需正确释放ByteBuf,精简ChannelPipeline,妥善处理异常,并深入理解Netty原理。通过代码审查、遵循最佳实践和监控日志,可提升代码质量和性能。掌握Netty,打造高效网络服务。
83 2
|
4月前
|
安全 NoSQL Java
网络安全-----Redis12的Java客户端----客户端对比12,Jedis介绍,使用简单安全性不足,lettuce(官方默认)是基于Netty,支持同步,异步和响应式,并且线程是安全的,支持R
网络安全-----Redis12的Java客户端----客户端对比12,Jedis介绍,使用简单安全性不足,lettuce(官方默认)是基于Netty,支持同步,异步和响应式,并且线程是安全的,支持R
|
5月前
|
消息中间件 存储 Java
美团面试:说说Netty的零拷贝技术?
零拷贝技术(Zero-Copy)是一个大家耳熟能详的技术名词了,它主要用于提升 IO(Input & Output)的传输性能。 那么问题来了,为什么零拷贝技术能提升 IO 性能? ## 1.零拷贝技术和性能 在传统的 IO 操作中,当我们需要读取并传输数据时,我们需要在用户态(用户空间)和内核态(内核空间)中进行数据拷贝,它的执行流程如下: ![](https://cdn.nlark.com/yuque/0/2024/png/92791/1706491312473-52f5904a-2742-4e99-9b78-995e9a8b9696.png?x-oss-process=image%2F
54 0
|
6月前
|
编解码 前端开发 Java
Java网络API之Netty深度解析
Java网络API之Netty深度解析
52 0
|
6月前
|
编解码 网络协议 Java
用Java的BIO和NIO、Netty实现HTTP服务器(一) BIO与绪论
用Java的BIO和NIO、Netty实现HTTP服务器(一) BIO与绪论