非阻塞IO模式原理

与阻塞模式对应的另一种模式叫非阻塞IO模式,在整个通信过程中读和写操作不会阻塞,当前处理线程不存在阻塞情况。从A机器到B机器它的通信过程是:A机器一条线程将通道设置为写事件后往下执行,而另外一条线程遍历到此通道有字节要写并往socket写数据,B机器一条线程遍历到此通道有字节要读,交给另外一条线程对socket读数据,处理完又把通道设置为写事件,遍历线程遍历到此通道有字节要写,又往socket写数据传往A机器,不断往下循环此操作直到完成通信。这个过程每台机器都有两类主要线程,一类是负责逻辑处理且将通道改为可写或可读事件的线程,另外一类是专门用于遍历通道并负责socket读写的线程,这种方式就是非阻塞IO模式。

在阻塞IO模式中,存在一个服务端套接字ServerSocket用于接收客户端连进来的Socket,而不管是阻塞还是非阻塞IO最终都需要获取socket才能进行读写操作,与阻塞模式对应,非阻塞模式用于接收客户端socket的对象是ServerSocketChannel,另外,阻塞模式直接使用Socket对象进行读写操作,而非阻塞模式则使用SocketChannel对象进行读写操作,但SocketChannel本质上最终也是通过Socket读取与写入,只是读取或写入时引入了缓冲区概念。最后,还有一个很重要的对象是选择器Selector,它提供对所有channel各种感兴趣事件的筛选功能,即哪些通道需要怎样的处理通过它选择出来的。

往下说说非阻塞模式实现的原理,如下图,ServerSocketChannel调用open()方法初始化封装在里面的socket服务并将ServerSocketChannel以OP_ACCEPT事件注册到Selector中,而操作系统则创建socket底层数据结构并监听客户端socket连接,对于客户端连接操作系统会统一放到一个队列中进行维护。接着是很重要的应用层轮询操作,不断执行Selector检索出感兴趣的事件,假如刚好有三个客户端socket连进来,Selector选择出三个OP_ACCEPT事件,调用ServerSocketChannel.accept()接收三个客户端通道SocketChannel对象,再将这三个客户端通道以OP_READ、OP_WRITE注册到Selector中以便后面进行读写操作,往下如果Selector遍历出OP_READ或OP_WRITE事件则可以对对应的channel进行读写操作了。

 

Selector在其中扮演最重要的角色,看看它是如何完成感兴趣的事件的筛选的。如上图,中间Selector便是它的大体结构,维护了registeredKeys、selectedKeys、cancelledKeys三个集合,还有一张channel与Key对应关系的表,而Key则包含了感兴趣事件集interestOps和已准备好的事件集readyOps。其中registeredKeys存放注册到Selector的所有key,而selectedKeys即是被选中的key,它是检测到registeredKeys中key感兴趣的事件发生后存放key的地方,cancelledKeys则是已经调用了cancel()方法待反注册的key。当应用层中Selector不断调用select()方法时,会先根据cancelledKeys去删除registeredKeys和selectedKeys对应的key以至取消对应的key,然后间接调用操作系统去做操作系统级别的select,一旦有registeredKeys感兴趣的事件则将对应事件的key添加到selectedKeys中,如selectedKeys已存在key了则将事件添加到key中的已准备好的事件集readyOps中。经过此番操作,当应用层调用Selector的selectedKeys()则取到被选中的key集,进而可以获取到感兴趣事件对应的channel,根据事件对channel进行操作。

    理解了非阻塞IO模式的原理有助于在实际场景中对网络IO的模式选型,一般在同时需要处理多个连接的高并发场景中会使用非阻塞NIO模式,它通过一个或少量线程去维护连接,而把具体的读写和逻辑处理交由其他线程处理,大大提高了机器的使用率,压榨机器CPU。而如果使用阻塞IO模式则可能线程都阻塞在IO而导致机器使用率较低。

========广告时间========鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。[为什么写《Tomcat内核设计剖析》](http://blog.csdn.net/wangyangzhizhou/article/details/74080321)=========================欢迎关注:![这里写图片描述](http://img.blog.csdn.net/20170509102539658?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3lhbmd6aGl6aG91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

========广告时间========鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。[为什么写《Tomcat内核设计剖析》](http://blog.csdn.net/wangyangzhizhou/article/details/74080321)=========================欢迎关注:![这里写图片描述](http://img.blog.csdn.net/20170509102539658?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3lhbmd6aGl6aG91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

时间: 2024-10-26 17:41:50

非阻塞IO模式原理的相关文章

Python异步非阻塞IO多路复用Select/Poll/Epoll使用

来源:http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的. 下面记录下分别基于Select/Poll/Epoll的echo server实现. Python Select Server,可监控事件数量有限制: #!/usr/bin/python # -*- coding: utf-8 -*- import select import sock

script的async属性以非阻塞的模式加载脚本_javascript技巧

1.HTML5实现了script的async属性,这个新的属性可以让js在浏览器中以非阻塞的模式加载,另外script还有一个defer属性,这个属性目前所有浏览器都已实现(除了firefox和chrome的早期版本),IE这方面做得好,从一开始就支持些属性. 复制代码 代码如下: //async <script async src="dquery.js" async></script> //defer <script async src="dq

Tornado Web Server 2.0发布 非阻塞IO的Web服务器软件

Tornado web server 是使用Python编写出来的一个极轻量级.高可伸缩性和非阻塞IO的http://www.aliyun.com/zixun/aggregation/17117.html">Web服务器软件,著名的 Friendfeed 网站就是使用它搭建的. Tornado 跟其他主流的Web服务器框架(主要是Python框架)不同是采用epoll非阻塞IO,响应快速,可处理数千并发连接,特别适用用于实时的Web服务. 要使用它,必须按照以下套件: 1)Python(建

一个高可扩展的基于非阻塞IO的服务器架构

原文链接   译者:mailto:ahahage@163.com 目录 线程体系结构 反应堆模式 组件架构 接收器 分配器 分配器级别事件处理器 应用程序级别事件处理器 总结 参考资料 如果你被要求去写一个高可扩展性的基于JAVA的服务器,你很快就会决定使用JAVA NIO包.为了让服务器跑起来,你可能会花很多时间阅读博客和教程来了解线程同步需要NIO SELECTOR类以及处理一些常见的陷阱.本文描述了一个面向连接基于NIO的服务器的基本架构.本文会先看一下一个首选的线程模型然后讨论服务器的一

Node.js 非阻塞IO和事件循环

非阻塞的IO模型 首先,IO操作无疑是耗时的,当服务器端接收到大量请求时,为每一个请求创建进程或线程的同时,也增加了额外的内存开销,也可能浪费更多的时间资源. 由于Node.js是事件驱动的,于是它使用了事件循环来解决IO操作带来的瓶颈问题.在Node.js中,一个IO操作通常会带有一个回调函数,当IO操作完成并返回时,就会调用这个回调函数,而主线程则继续执行接下来的代码.简单的用一个例子来说明这个问题: request('http://www.google.com', function(err

非阻塞IO服务器模型

我们来考虑一个情形,你跟千千万万个玩家是魔兽世界的超级粉丝,每周末准时组团打boss.每当周末游戏服务器就亚历山大,因为起码几十万用户同时在线.如果用我们的多线程阻塞服务器作为游戏服务器是否可行呢?先分析游戏服务器有哪些特点: ①  网络游戏并非像网页一样,打开一旦下载完就可以关闭连接结束.网游必须是有一个持久有状态的连接,每一个客户端都需要跟服务器存在一个持久的连接,以便快速及时发送消息.而随着并发用户数量的增加,多线程阻塞服务器不可能为每一个客户端分配一个线程. ②  跟一般的应用服务器不同

练习C之SELECT形式的非阻塞IO

呵呵,理解得不深,但毕竟手打全版,且无错.但select.h不知何处找头文件, 粘下来作个记录. POLL,EPOLL感觉代码类似,只是函数和系统实现不一样,,EPOLL目前最合理的.定位精确,算法复杂度最好. #include "select.h" #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/select.h> #include

关于网络IO中的同步、异步、阻塞、非阻塞

在高并发编程当中,我们经常会遇到一些异步.非阻塞等一些概念,一些常用的技术比如异步的httpclient.netty nio.nginx.node.js等,它们的原理大都跟异步.非阻塞有关.特别是在服务器开发中,并发的请求处理是个大问题,阻塞式的函数会导致资源浪费和时间延迟.通过事件注册.异步函数,开发人员可以提高资源的利用率,性能也会改善.其nginx和node.js处理并发都是采用的事件驱动异步非阻塞模式.其中nginx中处理并发用的是epoll,poll,queue等方式,node.js使

怎样通过MSG_WAITALL设置阻塞时间,IO模式精细讲解: MSG_DONTWAIT 、 MSG_WAITALL

首先给出MSDN上一段设置阻塞超时的代码:(网址为http://social.msdn.microsoft.com/Forums/zh-SG/visualcpluszhchs/thread/3d9daec0-f000-4bf1-add1-3beab8e398eb) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42