news 2026/6/20 9:52:25

【Netty源码解读和权威指南】第31篇:Netty零拷贝深度解析——性能极致的秘密武器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Netty源码解读和权威指南】第31篇:Netty零拷贝深度解析——性能极致的秘密武器

上一篇【第30篇】Netty写数据源码解析——write/flush背后的双队列设计
下一篇【第32篇】Netty背压机制——不让发送方"撑死"接收方


开篇故事

某文件传输系统,传输1GB文件CPU飙到90%。排查:每次发送都要memcpy从堆内拷贝到堆外!

优化后:使用FileRegion.TransferTo,直接DMA传输,CPU降到5%!

零拷贝 = 不进行CPU参与的memcpy


一、传统vs零拷贝对比

传统方式(4次拷贝+2次上下文切换): 磁盘→内核缓冲区→用户缓冲区→Socket缓冲区→网卡 ↑ DMA ↑ CPU memcpy ↑ CPU memcpy ↑ DMA 零拷贝(sendfile)(2次拷贝+0次上下文切换): 磁盘→内核缓冲区→Socket缓冲区→网卡 ↑ DMA ↑ DMA(仅描述符传递)

二、Netty四种零拷贝实现

2.1 CompositeByteBuf——组合多个ByteBuf

ByteBufheader=Unpooled.copiedBuffer("HTTP/1.1 200 OK\r\n".getBytes());ByteBufbody=Unpooled.copiedBuffer("Hello Netty".getBytes());CompositeByteBufcomposite=Unpooled.compositeBuffer();composite.addComponents(true,header,body);// 零拷贝!header和body的数据没有复制,只保存了引用

2.2 slice()——切片共享同一块内存

ByteBufbuf=Unpooled.buffer(1024);buf.writeBytes("Hello World".getBytes());ByteBufslice=buf.slice(0,5);// "Hello" 零拷贝!slice.setByte(0,'h');// 修改slice也影响原buf

2.3 wrap()——包裹字节数组

byte[]data="Hello".getBytes();ByteBufbuf=Unpooled.wrappedBuffer(data);// 零拷贝包裹

2.4 FileRegion——文件传输零拷贝

// 直接将文件数据DMA传输到Socket,不经过用户空间RandomAccessFilefile=newRandomAccessFile("largefile.dat","r");FileRegionregion=newDefaultFileRegion(file.getChannel(),0,file.length());ctx.writeAndFlush(region);

三、FileRegion源码

publicclassDefaultFileRegionextendsAbstractReferenceCountedimplementsFileRegion{privatefinalFileChannelfile;privatefinallongposition;privatefinallongcount;publiclongtransferTo(WritableByteChanneltarget,longpos)throwsIOException{returnfile.transferTo(this.position+pos,count-pos,target);}}// NioSocketChannel中使用protectedbooleandoWriteFileRegion(FileRegionregion){longwritten=region.transferTo(javaChannel(),region.transferred());// 底层调用:FileChannel.transferTo() → sendfile()系统调用}

四、实战:高性能文件服务器

importio.netty.bootstrap.ServerBootstrap;importio.netty.channel.*;importio.netty.channel.nio.NioEventLoopGroup;importio.netty.channel.socket.nio.NioServerSocketChannel;importio.netty.handler.codec.LineBasedFrameDecoder;importio.netty.handler.codec.string.StringDecoder;importjava.io.RandomAccessFile;publicclassZeroCopyFileServer{publicstaticvoidmain(String[]args)throwsException{EventLoopGroupboss=newNioEventLoopGroup(1);EventLoopGroupworker=newNioEventLoopGroup();try{newServerBootstrap().group(boss,worker).channel(NioServerSocketChannel.class).childHandler(newChannelInitializer<Channel>(){protectedvoidinitChannel(Channelch){ch.pipeline().addLast(newLineBasedFrameDecoder(1024));ch.pipeline().addLast(newStringDecoder());ch.pipeline().addLast(newFileSendHandler());}}).bind(8080).sync().channel().closeFuture().sync();}finally{boss.shutdownGracefully();worker.shutdownGracefully();}}staticclassFileSendHandlerextendsChannelInboundHandlerAdapter{publicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){Stringpath=((String)msg).trim();try{RandomAccessFilefile=newRandomAccessFile(path,"r");// 零拷贝发送文件!ctx.write(newDefaultFileRegion(file.getChannel(),0,file.length()));ctx.writeAndFlush("\r\n");}catch(Exceptione){ctx.close();}}}}

五、性能对比

方式CPU内存拷贝次数适用场景
传统read/write90%4次小文件
HeapBuf + write60%3次中等文件
DirectBuf + write30%2次大文件
FileRegion5%0次(DMA)超大文件

六、总结

方式原理
CompositeByteBuf多个ByteBuf零拷贝拼接
slice()同一块内存的不同视图
wrap()byte[]零拷贝包裹
FileRegionsendfile()系统调用,DMA传输

上一篇【第30篇】Netty写数据源码解析——write/flush背后的双队列设计
下一篇【第32篇】Netty背压机制——不让发送方"撑死"接收方


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/20 9:22:50

API安全实战:防刷、防爬、防泄漏的纵深防御体系构建

1. 项目概述&#xff1a;为什么API安全不再是“选修课”&#xff1f;干了这么多年后端开发&#xff0c;我越来越觉得&#xff0c;一个Web API上线后&#xff0c;真正的考验才刚刚开始。你以为写完业务逻辑、通过单元测试就万事大吉了&#xff1f;太天真了。流量一上来&#xff…

作者头像 李华
网站建设 2026/6/20 9:21:59

高效开源工具使用秘籍:快速掌握百度网盘下载解析的完整指南

高效开源工具使用秘籍&#xff1a;快速掌握百度网盘下载解析的完整指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘下载速度慢而烦恼吗&#xff1f;今天我要…

作者头像 李华
网站建设 2026/6/20 9:17:00

SQL注入攻防演进与纵深防御体系构建实战指南

1. 项目概述&#xff1a;为什么SQL注入依然是“头号威胁”&#xff1f;干了十几年安全&#xff0c;从当年用 or 11就能黑掉一个论坛&#xff0c;到今天各种WAF、RASP、ORM框架层层防护&#xff0c;SQL注入这个话题似乎老生常谈。但每次做渗透测试或应急响应&#xff0c;它依然稳…

作者头像 李华
网站建设 2026/6/20 9:13:05

GEMM 三向分块参数 M/N/K BlockSize 完整解释

GEMM 三向分块参数 M/N/K BlockSize 完整解释 GEMM 公式&#xff1a;CMNAMKBKNC_{MN} A_{MK} B_{KN}CMN​AMK​BKN​ 三个维度对应三套分块参数&#xff1a; M_block&#xff1a;A 矩阵行维度分块大小&#xff08;选项A&#xff09;N_block&#xff1a;B 矩阵列维度分块大小&…

作者头像 李华