简单聊下IO复用
没图,不分析API
Java中IO API的发展:
Socket -> SocketChannel -> AsynchronousSocketChannel
ServerSocket -> ServerSocketChannel -> AsynchronousServerSocketChannel
同步/阻塞 -> 同步/非阻塞(多路复用) -> 异步
想简单聊下多路复用。多路复用需要配合Reactor模式,前者解决技术上的问题,后者解决软件工程的问题。
技术上的问题,是将IO操作中等待和非等待的部分分开处理。我们都知道IO操作分为两个部分:
1、等待数据就绪
2、处理数据
众所周知的几种IO模型(阻塞、非阻塞、多路复用、信号驱动、异步)就是区别于这两个阶段,当需要处理很多连接的时候(高并发的情况),容易想到的是使用多线程技术,比如最简单的One-connection-Per-thread模式,但是因为等待数据不可避免,造成的结果是线程不停的休眠-唤醒的切换,导致CPU不堪重负。
IO复用的目的:将这两个阶段分开处理,让一个线程(而且是内核级别的线程)来处理所有的等待,一旦有相应的IO事件发生就通知继续完成IO操作,虽然仍然有阻塞和等待,但是等待总是发生在一个线程,这时使用多线程可以保证其他线程一旦唤醒就是处理数据,当然这需要非阻塞IO API的支持(比如非阻塞套接字)。Linux2.6之前的select,poll以及之后的epoll都是IO复用技术的实现。select和poll基本一致,epoll是对它们的改进版本。但总的来说它们都还不是真正的异步IO,因为它们在IO读写的时候仍然是阻塞的、同步的(完成一件事后才能做另外一件事)。异步IO是指“处理数据”这一阶段也是非阻塞的。Windows上的IOCP(完成端口)才是真正的AIO,理论上它比Linux的epoll更先进。
至于select、poll和epoll的区别,推荐这篇文章:http://www.cnblogs.com/Anker/p/3265058.html。简单来说:select,poll无脑的轮询,忽略了高并发下,轮询本身成了瓶颈,而epoll使用回调实现了轮询真正需要处理的连接。
Reactor模式是为了我们更简单的使用IO复用技术。它是一种并发IO模式,其他的模式还有多进程,多线程等。Reactor本身也有很多变种,比如thread per request,worker thread,thread pool,multiple reactors...网上这方面的资料很多。虽然网上关于reactor和多线程模孰优孰劣还有争论(Reactor最明显的一个缺点是无法充分利用多核的优势),但是大部分高并发的框架或组建都是基于reactor的,比如MINA,Netty,再比如Redis,Nginx(有多个工作进程来充分利用多核的优势)。关于Java中的IO复用可以看Doug Lea大神的Scalable IO in Java(http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf)。
至于JDK1.7中出现的Asynchronous I/O,只要是运行Linux上肯定无外乎epoll,那是不是可以说本质上仍然不是真正的异步IO呢?个人觉得异步这个概念是有粒度的,不可能做到完全的异步。JDK1.7中的AIO从编程的角度对程序员来说确是异步的,我们不用像在多路复用中那样自己去select了,我们需要做的就是在completion handlers中处理业务逻辑。
另外提一点:操作系统底层的IO操作都是异步的——IO中断,只不过同步更符合正常人的思维,更易于理解。
最后关于异步IO还想补充一点,虽然异步IO的第二阶段也是非阻塞的,但是仍然有优化空间。就是在数据从内核copy到用户空间这个过程,Netty就使用了Zero-Copy技术来优化这个步骤(http://my.oschina.net/plucury/blog/192577),另外还有MMAP。
欢迎斧正!
简单聊下IO复用的更多相关文章
- 简单聊下Unicode和UTF-8
今晚听同事分享提到这个,简单总结下. ## Unicode字符集 Unicode的出现是因为ASCII等其他编码码不够用了,比如ASCII是英语为母语的人发明的,只要一个字节8位就能够表示26个英文字 ...
- 简单聊下.NET6 Minimal API的使用方式
前言 随着.Net6的发布,微软也改进了对之前ASP.NET Core构建方式,使用了新的Minimal API模式.之前默认的方式是需要在Startup中注册IOC和中间件相关,但是在Minimal ...
- 一只简单的网络爬虫(基于linux C/C++)————浅谈并发(IO复用)模型
Linux常用的并发模型 Linux 下设计并发网络程序,有典型的 Apache 模型( Process Per Connection ,简称 PPC ), TPC ( Thread Per Conn ...
- Libevent的IO复用技术和定时事件原理
Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...
- IO复用(Reactor模式和Preactor模式)——用epoll来提高服务器并发能力
上篇线程/进程并发服务器中提到,提高服务器性能在IO层需要关注两个地方,一个是文件描述符处理,一个是线程调度. IO复用是什么?IO即Input/Output,在网络编程中,文件描述符就是一种IO操作 ...
- 高级IO复用应用:聊天室程序
简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户.这里采用IO复用poll技术.客户端采用了splice零拷贝.服务端采用了空间换时间(分配超大的用户数 ...
- Linux中的IO复用接口简介(文件监视?)
I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...
- IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别参考
参考https://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral IO复用,AI ...
- IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别(百度)
如果面试问到IO操作,这篇文章提到的问题,基本是必问,百度的面试官问我三个问题 (1)什么是NIO(Non-blocked IO),AIO,BIO (2) java IO 与 NIO(New IO)的 ...
随机推荐
- app整体搭建环境:tabBar切换不同控制器的封装(自定义导航+自定义uiviewcontroler+系统自带tabbar+自定义tabbarController)
首先,一个app的搭建环境非常重要.既要实现基本功能,又要考虑后期优化的性能. 现在很多应用不仅仅是系统自带的控制器,由于需求复杂,基本上需要自定义多控制器来管理. 新建一个BasicNavigati ...
- BASE64Decoder 编码(sun.jar)
Base64 是网络上最常见的用于传输8Bit 字节代码的编码方式之一,大家可以查看RFC2045 -RFC2049 ,上面有MIME 的详细规范. Base64 要求把每三个8Bit 的字节转换为
- CocoaPods Podfile 文件写法有讲究
最近做到一些项目想到用 OC/Swift混编的问题.为了搞懂 bridge header 这个文件是咋个情况.却一致报错.最后不知不觉发现问题问题居然出在 Podfile 上. 开始我是从 IT 江湖 ...
- impdp使用
创建一个dir,dump_dir1,将备份文件放在下面 impdp szfetsc_card/123456 directory=dump_dir1 dumpfile=130912.dmp REMAP_ ...
- Linq之Expression初见
目录 写在前面 系列文章 Expression 表达式树创建方式 一个例子 总结 写在前面 上篇文章介绍了扩展方法,这篇文章开始将陆续介绍在linq中使用最多的表达式树的相关概念,以概念及例子一一列出 ...
- EF,MVC相关项目请参见→
End_Test和YM_EF抽象工厂 这两个项目
- Go语言开发环境搭建
1.Go的安装 (1)下载go安装程序 下载地址:https://golang.org/dl/ (墙内下载地址http://www.golangtc.com/download),如果是您的系统是win ...
- 每天一个linux命令(43):lsof命令
lsof(list open files) 是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以 如传输控制 ...
- JDK的目录
要想深入了解Java必须对JDK的组成, 本文对JDK6里的目录做了基本的介绍,主要还是讲解 了下JDK里的各种可执行程序或工具的用途 Java(TM) 有两个平台 JRE 运行平台,包括Java虚拟 ...
- Tomcat tomcat-users.xml详解
conf/tomcat-users.xml <?xml version='1.0' encoding='utf-8'?> <tomcat-users> <role rol ...