Netty-初探

本文探讨了网络编程中直接内存与堆内存的性能差异,重点介绍了JVM如何处理堆内存数据,以及Linux中的零拷贝技术如mmap和sendfile在Kafka和Netty中的应用。文章还比较了不同I/O模型,如NIO、BIO和Epoll,并讨论了为何选择Netty而非Netty5或Mina的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

最近开始学习网络编程这一块,特此总结

直接内存为什么比堆内内存要快?

JVM在发送堆内数据给远程时,首先会把这部分数据复制到堆外的一块内存空间(防止GC过程中文件引用地址发生变化带来的问题),然后再发送给远程应用。而直接内存省去了这个复制步骤,好处就是更快速并且减少了GC

直接内存的缺点就是难以控制,发生内存泄漏时难以排查。比较适合存简单对象扁平化

Linux常见的零拷贝有哪些?

  • mmap内存映射

直接将文件从硬盘拷贝到用户空间,不再有文件内容从硬盘拷贝到内核空间的缓冲区

扩展:Kafka中有一个Broker用来管理消息,Producer需要把消息发送给Broker,Broker收到消息以后肯定是要做持久化的。Kafka号称单机百万级吞吐量,为什么持久化速度这么快呢?就是使用了磁盘顺序写和mmap的零拷贝技术

java.nio.MappedByteBuffer这个类就是mmap在 Java中应用

  • sendfile

Linux2.1开始支持

DMA模块直接将数据从内核缓冲区传递给协议引擎,注意需要硬件设备支持

DMA:Direct Memory Access,直接内存存取

扩展:同样是Kafka的Broker,Consumer订阅消息时,Broker把消息的数据从磁盘发送到网卡的发送缓冲区这个过程就使用了sendfile技术

FileChannel.transferToFileChannel.transferFrom 就是在Java中的应用

  • splice

Linux2.6.17开始支持

相比sendfile不需要硬件支持

splice直接将两个内核空间的buffer进行pipe(sendfile在DMA硬件不支持的情况下,这里需要一次CPU拷贝)

Netty的零拷贝实现

  • 网络通信

Netty的发送和接收ByteBuffer使用直接内存,减少了堆内存到直接内存的拷贝

  • 缓存操作

Netty提供了CompositeByteBuf类,将多个ByteBuf合并成一个逻辑上的ByteBuf,防止它们之间的互相拷贝

  • 文件传输

Netty通过FileRegion包装的FileChannel.transferTo实现文件传输,直接将文件缓冲区的数据发送到目标Channel

Linux常见的I/O编程模型

1、阻塞IO(blocking IO),BIO

2、非阻塞IO(nonblocking IO)

3、IO复用(select、epoll和poll,IO multiplexing),NIO

4、信号驱动IO(Single Driven IO,SIGIO)

5、异步IO(asynchronous IO)

常见的就是BIO和NIO,严格意义上前四种都是阻塞的,过程中间都存在阻塞,只不过阻塞时可以做其他的事情

通常都会说同步阻塞和异步非阻塞,但是并不代表同步非阻塞和异步阻塞不能用

同步非阻塞:获取资源不存在,线程阻塞了,线程去做其他事,线程会频繁的查询资源是否存在,消耗很多CPU

异步阻塞:Java中创建Future,然后马上调用get方法获取资源,没有多大的意义

总给:同步非阻塞和异步阻塞这两种方式太傻,所以不会有人去使用

接下来主要学习的是NIO

NIO的优势:可以用很少的线程服务很多的用户

select、poll 和 epoll 模型的区别?

// fd数组存储,有连接上限
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
// fd链表存储,无连接上限
int poll (struct pollfd *fds, unsigned int nfds, int timeout);

// 创建EventPoll对象
int epoll_create(int size);
// 增加或删除监听事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 
// 阻塞直到有事件发生
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
selectpollepoll
支持一个进程能打开的最大连接数FD_SETSIZE定义,32位机器是32*32大小,64位机器是32*64大小。可以修改但不建议本质上和select相同,没有最大连接数限制,链表存储连接数受限机器内存大小
FD剧增带来的IO效率问题对连接线性遍历,FD增加后效率线性下降同select根据fd的callback函数实现,活跃的socket才会调用callback。活跃socket多的情况下也有性能问题
消息传递方式内核将消息传递到用户空间,经过拷贝内核将消息传递到用户空间,经过拷贝内核和用户空间共享一块内存

总结:

使用时根据场合以及这三种方式各自的特点

1、表面上epoll效率最高,但是在连接数少并且都很活跃的情况下,select和poll的性能更高,epoll通知机制需要很多回调

2、select低效是因为轮询,但是低效也是相对的,也可以通过良好的设计改善

Netty简述

Netty的优势

1、API使用简单,开发门槛低;

2、功能强大,预置了多种编解码功能,支持多种主流协议;

3、定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展;

4、性能高,通过与其他业界主流的NIO框架对比,Netty的综合性能最优;

5、成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发人员不需要再为NIO的BUG而烦 恼;

6、社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会加入;

7、经历了大规模的商业应用考验,质量得到验证

为什么不用Netty5

已经停止开发了,其底层的AIO模型,参考了NIO的epoll模型,性能并没有提高很多,而且还会带来很多的异步回调问题。

而且操作系统对AIO的支持不够成熟,处理回调结果速度跟不上处理需求

作者原话: (为什么使用NIO为不是AIO)

Not faster than NIO (epoll) on unix systems (which is true)

There is no daragram suppport

Unnecessary threading model (too much abstraction without usage)

为什么不用Mina

Mina几乎不更新了。Mina也是Netty的作者做出来的,后来作者继续回去做Netty了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值