标签:
杂谈 |
基本的IO编程过程(包括网络IO和文件IO)是,打开文件描述符(windows是handler,java是stream或channel),多路捕获(Multiplexe,即select和poll和epoll)IO可读写的状态,而后可以读写的文件描述符进行IO读写,由于IO设备速度和CPU内存比速度会慢,为了更好的利用CPU和内存,会开多线程,每个线程读写一个文件描述符。
但C10K问题,让我们意识到在超大数量的网络连接下,机器设备和网络速度不再是瓶颈,瓶颈在于操作系统和IO应用程序的沟通协作的方式。
举个例子,一万个socket连接过来,传统的IO编程模型要开万个线程来应对,还要注意,socket会关闭打开,一万个线程要不断的关闭线程重建线程,资源都浪费在这上面了,我们算建立一个线程耗1M内存,1万个线程机器至少要10G内存,这在IA-32的机器架构下基本是不可能的(要开PAE),现在x64架构才有可能舒服点,要知道,这仅仅是粗略算的内存消耗。别的资源呢?
所以,高性能的网络编程(即IO编程),第一,需要松绑IO连接和应用程序线程的对应关系,这就是非阻塞(nonblocking)、异步(asynchronous)的要求的由来(构造一个线程池,epoll监控到有数的fd,把fd传入线程池,由这些worker thread来读写io)。第二,需要高性能的OS对IO设备可读写(数据来了)的通知方式:从level-triggered notification到edge-triggered notification,关于这个通知方式,我们稍后谈。
需要注意异步,不等于AIO(asynchronous IO),linux的AIO和java的AIO都是实现异步的一种方式,都是渣,这个我们也接下来会谈到。
针对前面说的这两点,我们看看select和poll的问题
这两个函数都在每次调用的时候要求我们把需要监控(看看有没有数据)的文件描述符,通过数组传递进入内核,内核每次都要扫描这些文件描述符,去理解它们,建立一个文件描述符和IO对应的数组(实际内核工作会有好点的实现方式,但可以这么理解先),以便IO来的时候,通知这些文件描述符,进而通知到进程里等待的这些select、poll。当有一万个文件描述符要监控的时候呢(一万个网络连接)?这个工作效率是很低的,资源要求却很高。
我们看epoll
epoll很巧妙,分为三个函数,第一个函数创建一个session类似的东西,第二函数告诉内核维持这个session,并把属于session内的fd传给内核,第三个函数epoll_wait是真正的监控多个文件描述符函数,只需要告诉内核,我在等待哪个session,而session内的fd,内核早就分析过了,不再在每次epoll调用的时候分析,这就节省了内核大部分工作。这样每次调用epoll,内核不再重新扫描fd数组,因为我们维持了session。
说道这里,只有一个字,开源,赞,众人拾柴火焰高,赞。
epoll的效率还不仅仅体现在这里,在内核通知方式上,也改进了,我们先看select和poll的通知方式,也就是level-triggered notification,内核在被DMA中断,捕获到IO设备来数据后,本来只需要查找这个数据属于哪个文件描述符,进而通知线程里等待的函数即可,但是,select和poll要求内核在通知阶段还要继续再扫描一次刚才所建立的内核fd和io对应的那个数组,因为应用程序可能没有真正去读上次通知有数据后的那些fd,应用程序上次没读,内核在这次select和poll调用的时候就得继续通知,这个os和应用程序的沟通方式效率是低下的。只是方便编程而已(可以不去读那个网络io,方正下次会继续通知)。
于是epoll设计了另外一种通知方式:edge-triggered notification,在这个模式下,io设备来了数据,就只通知这些io设备对应的fd,上次通知过的fd不再通知,内核不再扫描一大堆fd了。
基于以上分析,我们可以看到epoll是专门针对大网络并发连接下的os和应用沟通协作上的一个设计,在linux下编网络服务器,必然要采用这个,nginx、php的国产异步框架swool、varnish,都是采用这个。
注意还要打开epoll的edge-triggered notification。而java的NIO和NIO.2都只是用了epoll,没有打开edge-triggered notification,所以不如JBoss的Netty。
接下来我们谈谈AIO的问题,AIO希望的是,你select,poll,epoll都需要用一个函数去监控一大堆fd,那么我AIO不需要了,你把fd告诉内核,你应用程序无需等待,内核会通过信号等软中断告诉应用程序,数据来了,你直接读了,所以,用了AIO可以废弃select,poll,epoll。
但linux的AIO的实现方式是内核和应用共享一片内存区域,应用通过检测这个内存区域(避免调用nonblocking的read、write函数来测试是否来数据,因为即便调用nonblocking的read和write由于进程要切换用户态和内核态,仍旧效率不高)来得知fd是否有数据,可是检测内存区域毕竟不是实时的,你需要在线程里构造一个监控内存的循环,设置sleep,总的效率不如epoll这样的实时通知。所以,AIO是渣,适合低并发的IO操作。所以java7引入的NIO.2引入的AIO对高并发的网络IO设计程序来说,也是渣,只有Netty的epoll+edge-triggered notification最牛,能在linux让应用和OS取得最高效率的沟通。
注:阻塞IO和异步IO基本是一个意思,只是描述同一个东西的不同方面。
http://en.wikipedia.org/wiki/Asynchronous_I/O
In computer science, asynchronous I/O, or non-blocking I/O is a form of input/output processing that permits other processing to continue before thetransmission has finished.
转自:http://blog.sina.com.cn/s/blog_4c8c58ce0102vkbo.html
相关推荐
9. **NIO 和 EPOLL**:Netty 可以利用 Java NIO 或者 Linux 的 EPOLL(在其他平台上也有相应的选择),提供高性能的非阻塞 I/O。 10. **线程模型**:Netty 的线程模型设计得很灵活,可以根据需求选择单线程、多线程...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个"Netty-4.1.19.Final小包"包含了Netty框架的多个组件,便于开发者在Java环境中构建网络应用。 在提供的...
Netty是一个高性能、异步事件驱动的网络应用程序框架,常用于开发高效的服务器和客户端应用,尤其是在高并发场景下。 【描述】中再次强调了这是针对Java高级开发者的Netty面试准备材料,意味着这份资料可能包含了...
9. **NIO与EPOLL**:Netty同时支持Java的NIO和Linux的EPOLL(高效I/O)事件通知机制,EPOLL在Linux环境下能提供更好的性能。 10. **零拷贝**:Netty通过组合使用DirectByteBuffer和FileRegion,实现了数据传输的零...
11. **NIO 和 EPOLL**: Netty 支持Java NIO和Linux下的EPOLL(高效套接字)两种不同的选择,EPOLL在Linux环境下提供了更高的性能。 通过这个“netty5绝版资料”,你将能够学习到如何配置和使用这些组件,以及如何...
《深入Hotspot源码与Linux内核理解NIO与Netty线程模型》这份资料主要探讨了Java的Hotspot虚拟机源码、Linux内核、非阻塞I/O(NIO)以及Netty框架的线程模型。这些知识点在构建高性能、高并发的网络应用中至关重要。 ...
Netty 是一款高性能、异步事件驱动的网络应用程序框架,专为开发快速、可扩展的网络应用程序而设计。它的核心特性在于提供了对TCP、UDP和文件传输的支持,并且基于NIO(非阻塞IO)实现,确保了在高并发场景下的高效...
7. **线程模型优化**:Netty采用了NIO(非阻塞I/O)和Epoll(在Linux上)来提高并发性能,使得它在高并发场景下表现出色。 8. **Error Handling**:Netty提供了一套完整的错误处理机制,可以优雅地处理异常情况,...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个“netty-3.7.0官方API所有jar包”提供了Netty 3.7.0版本的完整API文档、所有相关的jar包以及示例代码,...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个“netty-4.1.4-jar包”包含了两个重要的文件:“netty-all-4.1.17.Final.jar”和“netty-all-4.1.17....
在Java NIO框架的基础上,Netty为开发者提供了更高级别的抽象,减少了直接使用NIO所需的复杂性,比如Java多线程和网络编程。 使用Netty的主要原因包括: 1. 数据格式封装:Netty通过编码器和解码器实现了对多种...
Netty是一个高性能、异步事件驱动的网络应用框架,专为Java开发人员设计,用于构建可伸缩且高效的服务器和客户端。Netty的出现解决了传统Java API(如BIO)和NIO在实现网络通信时的诸多问题,尤其是在高并发场景下的...
为了实现长连接,Netty 使用了 NIO(非阻塞 I/O)和 EPOLL(在 Linux 上)这样的高效 I/O 模型,使得在高并发情况下仍能保持低延迟和高吞吐量。 接下来,我们谈谈如何在连接断开后实现自动重连。在实际网络环境中,...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本文档是Netty的基础应用实战教程,涵盖了从环境设置到高级特性的全面讲解。 首先,Netty 的核心特性是其...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,专为开发可伸缩且高度并发的服务器而设计。在深入探讨 Netty 的源代码之前,我们先来了解一下它的核心概念和架构。 Netty 提供了一种简化网络编程的方式,...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,专为 Java 平台设计,用于快速开发可维护的高性能协议服务器和客户端。在高并发场景下,Netty 展现出强大的性能优势,使得它在分布式系统、微服务、云计算等...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个“netty-4.1.zip”压缩包包含的是Netty框架的4.1版本源代码,对于Java后端开发者来说,深入学习和理解...
- **定义**: Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器与客户端。 - **目标用户**: 适合Java网络编程新手及有经验的开发者。 - **核心优势**: 提供了简单易用的API,将...
2. **在线教程与博客**:如《高性能网络编程(五):一文读懂高性能网络编程中的 I/O 模型》、《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》等。 3. **社区讨论与问答**:加入 Netty 的官方论坛或 ...