非阻塞与异步
在标准的网络服务器的构建中,IO模式会按照Blocking/Non-Blocking、Synchronous/Asynchronous这两个标准进行分类,其中Blocking与Synchronous大同小异,而NIO与Async的区别在于NIO强调的是轮询(Polling),而Async强调的是通知(Notification)。譬如在一个典型的单进程单线程Socket接口中,阻塞型的接口必须在上一个Socket连接关闭之后才能接入下一个Socket连接。而对于NIO的Socket而言,服务端应用会从内核获取到一个特殊的 “Would Block” 错误信息,但是并不会阻塞到等待发起请求的Socket客户端停止。
一般来说,在Linux系统中可以通过调用独立的 select
或者 epoll
方法来遍历所有读取好的数据,并且进行写操作。而对于异步Socket而言(譬如Windows中的Sockets或者.Net中实现的Sockets模型),服务端应用会告诉IO Framework去读取某个Socket数据,在数据读取完毕之后IO Framework会自动地调用你的回调(也就是通知应用程序本身数据已经准备好了)。以IO多路复用中的Reactor与Proactor模型为例,非阻塞的模型是需要应用程序本身处理IO的,而异步模型则是由Kernel或者Framework将数据准备好读入缓冲区中,应用程序直接从缓冲区读取数据。
-
同步阻塞:在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。
-
同步非阻塞:在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。
-
异步非阻塞:在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。
而在并发IO的问题中,较常见的就是所谓的C10K问题,即有10000个客户端需要连上一个服务器并保持TCP连接,客户端会不定时的发送请求给服务器,服务器收到请求后需及时处理并返回结果。
Links