Netty-初探

引言

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

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

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

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

Linux常见的零拷贝有哪些?

  • mmap内存映射

Netty-初探_第1张图片

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

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

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

  • sendfile

Linux2.1开始支持

Netty-初探_第2张图片

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

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

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

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

  • splice

Linux2.6.17开始支持

Netty-初探_第3张图片

相比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);
select poll epoll
支持一个进程能打开的最大连接数 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了。

你可能感兴趣的:(网络,java)