处理大并发之一 对异步非阻塞的理解

在研究nginx和node.js的时候常会遇到异步、非阻塞等,之前自己也经常使用epoll,对其同步与阻塞,异步与非阻塞有了一定的认识,现对参考资料总结下。

首先讨论下使用事件驱动,异步编程的优点:

充分利用了系统资源,执行代码无须阻塞等待某种操作完成,有限的资源可以用于其他的任务。其非常适合于后端的网络服务编程。

在服务器开发中,并发的请求处理是个大问题,阻塞式的函数会导致资源浪费和时间延迟。通过事件注册、异步函数,开发人员可以提高资源的利用率,性能也会改善。其nginx和node.js处理并发都是采用的事件驱动异步非阻塞模式。其中nginx中处理并发用的是epoll,poll,queue等方式,node.js使用的是libev,它们对大规模的HTTP请求处理的都很好。

阻塞

《node.js开发指南》是这样定义的:线程在执行中如果遇到(I/O 操作)如磁盘读写或网络通信,通常要耗费较长的时间,这时操作系统会剥夺这个线程的 CPU 控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为 阻塞。当 I/O 操作完毕时,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行。这种 I/O 模式就是通常的同步式 I/O(Synchronous I/O)或阻塞式 I/O(Blocking I/O)。

非阻塞

非阻塞是这样定义的,当线程遇到 I/O 操作时,不会以阻塞的方式等待 I/O 操作的完成或数据的返回,而只是将 I/O 请求发送给操作系统,继续执行下一条语句。当操作系统完成 I/O 操作时,以事件的形式通知执行 I/O 操作的线程,线程会在特定时候处理这个事件。

对比阻塞与非阻塞

阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。

非阻塞模式下,一个线程永远在执行计算操作,这个线程所使用的 CPU 核心利用率永远是 100%,I/O 以事件的方式通知。

在阻塞模式下,多线程往往能提高系统吞吐量,因为一个线程阻塞时还有其他线程在工作,多线程可以让 CPU 资源不被阻塞中的线程浪费。

而在非阻塞模式下,线程不会被 I/O 阻塞,永远在利用 CPU。多线程带来的好处仅仅是在多核 CPU 的情况下利用更多的核。

来看看《深入浅出Node.js》对异步I/O的解释,在操作系统中,程序运行的空间分为内核空间和用户空间。我们常常提起的异步I/O,其实质是用户空间中的程序不用依赖内核空间中的I/O操作实际完成,即可进行后续任务。

I/O的阻塞与非阻塞的解释

阻塞模式的I/O会造成应用程序等待,直到I/O完成。同时操作系统也支持将I/O操作设置为非阻塞模式,这时应用程序的调用将可能在没有拿到真正数据时就立即返回了,为此应用程序需要多次调用才能确认I/O操作完全完成。

I/O的同步与异步I/O的同步与异步出现在应用程序中。如果做阻塞I/O调用,应用程序等待调用的完成的过程就是一种同步状况。相反,I/O为非阻塞模式时,应用程序则是异步的。

参照《node.js入门经典》中对同步的解释,同步的代码意味着每一次执行一个操作,在一个操作完成之前,代码的执行会被阻塞,无法移到下一个操作上。也就是说代码的执行会在函数返回前停止。直到函数返回后,代码才会继续执行。

相反,异步就意味着函数的执行无需等待某个操作的结果就可以继续执行,其操作的结果会在事件发生时由回调来处理。

异步I/O优缺点

使用同步IO,它的优点是可以使程序调试方便,但是它的缺点也是明显的,程序的执行过程中如果入到一些耗时的IO操作,程序的执行都要等待该IO的完成,在这个等待的过程中,程序无法充分利用CPU,导致了CPU的闲置,为了充分利用CPU,和IO并行操作,常用的方法有2中:

(1)多线程单进程

多线程的设计之处就是为了在共享的程序空间中,实现并行处理任务,从而达到充分利用CPU的效果。

多线程缺点:

其一、执行时(线程切换)上下文交换的开销较大,一个线程大约需要2M的内存空间,占用资源较大。

其二、状态同步(锁)的问题,它也使得程序的编写和调用复杂化。

(2)单线程多进程

为了避免多线程造成的使用不便问题,有的语言选择了单线程保持调用简单化,采用启动多进程的方式来达到充分利用CPU和提升总体的并行处理能力。它的缺点在于业务逻辑复杂时(涉及多个I/O调用),因为业务逻辑不能分布到多个进程之间,事务处理时长要远远大于多线程模式。

异步I/O与轮询技术

当进行非阻塞I/O调用时,要读到完整的数据,应用程序需要进行多次轮询,才能确保读取数据完成,以进行下一步的操作。轮询技术的缺点在于应用程序要主动调用,会造成占用较多CPU时间片,性能较为低下。现存的轮询技术有以下这些: read、select、poll、epoll、pselect、kqueue

read是性能最低的一种,它通过重复调用来检查I/O的状态来完成完整数据读取。

select是一种改进方案,通过对文件描述符上的事件状态来进行判断。

操作系统还提供了poll、epoll等多路复用技术来提高性能。

轮询技术满足了异步I/O确保获取完整数据的保证。但是对于应用程序而言,它仍然只能算时一种同步,因为应用程序仍然需要主动去判断I/O的状态,依旧花费了很多CPU时间来等待。上一种方法重复调用read进行轮询直到最终成功,用户程序会占用较多CPU,性能较为低下。而实际上操作系统提供了select方法来代替这种重复read轮询进行状态判断。select内部通过检查文件描述符上的事件状态来进行判断数据是否完全读取。但是对于应用程序而言它仍然只能算是一种同步,因为应用程序仍然需要主动去判断I/O的状态,依旧花费了很多CPU时间等待,select也是一种轮询。

理想的异步I/O模型

理想的异步I/O应该是应用程序发起异步调用,而不需要进行轮询,进而处理下一个任务,只需在I/O完成后通过信号或是回调将数据传递给应用程序即可。

暂时就整理这么多吧,感觉好多看过的东西都忘记了,回头会写一篇关于epoll使用的详细例子,该例子支持2W并发是通过的。哎,今天状态不好,写的不好,本打算自己多加点什么的,结果都是参考别人的,如有错误请大家指正,谢谢。

参考资料:

《node.js入门经典》 George Ornbo 著 傅强 陈宗赋 译 人民邮电出版社

《深入浅出node.js》

《node.js开发指南》 BYVoid 人民邮电出版社

如是转载,请指明原出处:http://blog.csdn.net/feitianxuxue,谢谢合作!

处理大并发之一 对异步非阻塞的理解相关推荐

  1. java 异步_聊聊java高并发系统之异步非阻塞

    作者:孙伟,目前负责京东商品详情页统一服务系统,写过java,写过ngx_lua,还写过storm等,喜欢学习研究新事物. 在做电商系统时,流量入口如首页.活动页.商品详情页等系统承载了网站的大部分流 ...

  2. 同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...

  3. 同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO

    在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作. 在比较这两个模式之前,我们首先的搞明白 ...

  4. 真正的 Tornado 异步非阻塞

    其中 Tornado 的定义是 Web 框架和异步网络库,其中他具备有异步非阻塞能力,能解决他两个框架请求阻塞的问题,在需要并发能力时候就应该使用 Tornado. 但是在实际使用过程中很容易把 To ...

  5. 同步阻塞、同步非阻塞、异步阻塞、异步非阻塞与 I/O 多路复用、Java NIO 之间的联系

    同步阻塞.同步非阻塞.异步阻塞.异步非阻塞与 I/O 多路复用.Java NIO 之间的联系 先验知识 此处的异步指的是什么 同步.异步.阻塞.非阻塞 同步阻塞.同步非阻塞.异步阻塞.异步非阻塞 一个 ...

  6. Nginx的异步非阻塞

    转载地址:https://blog.csdn.net/dutsoft/article/details/55224755 同步与异步 同步与异步的理解 同步与异步的重点在消息通知的方式上,也就是调用结果 ...

  7. AIO,BIO,NIO:同步阻塞式IO,同步非阻塞IO,异步非阻塞IO

    BIO,同步阻塞式IO,简单理解:一个连接一个线程 NIO,同步非阻塞IO,简单理解:一个请求一个线程 AIO,异步非阻塞IO,简单理解:一个有效请求一个线程 IO:阻塞IO BIO:同步阻塞IO.服 ...

  8. 两段文章清楚弄明白什么是异步IO、同步IO、同步阻塞IO、同步非阻塞IO、异步阻塞IO、异步非阻塞IO

    百科解释:异步IO_百度百科 先看2,再看1,会理解的更好! 1. 2.阻塞和非阻塞 # 阻塞和非阻塞关注的是程序在等待调用结果时的状态 # 阻塞调用是指调用结果返回之前,当前线程会被挂起.调用线程只 ...

  9. tornado异步非阻塞实现方式

    目录 tornado异步非阻塞实现方式 1.多线程 2.老版协程 3.新版协程 实验 1.完全阻塞,同步代码 2.老版本协程 3新版本协程 4 多线程+新版协程,线程函数失效 5.线程+不声明异步,可 ...

最新文章

  1. ?:在正则表达式中什么意思
  2. AI如何影响经济周期?诺奖得主表态:保持关注,我很乐观
  3. SOA和SaaS的区别
  4. Python 计算Mesh顶点法向量
  5. mysql分区跨机器_(转) mysql的分区技术 .
  6. netty 压缩比_使Netty 4中的HTTP内容压缩工作
  7. python爬虫淘宝手机_【Python3 爬虫】14_爬取淘宝上的手机图片
  8. wp8.1 Study11:APP里文件读写和使用XML和Json序列化
  9. 2020年Java讲课笔记目录
  10. 阿里开源自研语音识别模型DFSMN 准确率高达96.04%
  11. 【十分钟开发物联网】楼宇访客门禁管理(Wifi版)
  12. 计算机类科技论文发表,计算机类科技论文
  13. VS2008安装部署应用程序安装包制作过程
  14. java 堆栈的声明_Java 堆栈
  15. python 动态执行 内存变化_深入理解python数组的动态扩容机制以及摊销分析
  16. 基于pytorch训练的VGG16神经网络模型完成手写数字的分割与识别
  17. 49个excel常用技巧(三)
  18. css实现3d正方体旋转
  19. html静态网站登陆验证,静态页面js加密URL密码验证
  20. 企业高性能缓存----varnish

热门文章

  1. 加载Hadoop+spark镜像文件需要修改的配置文件
  2. 【数学和算法】初识卡尔曼滤波器(六)
  3. 【Linux】13.linux内核切换
  4. Caffe学习系列(22):caffe图形化操作工具digits运行实例
  5. MySql 里的IFNULL、NULLIF和ISNULL用法
  6. 攻破JAVA NIO技术壁垒
  7. 使用BigDecimal进行精确运算
  8. 有关可变形部件模型(Deformable Part Model)的一些说明
  9. Ukbench图像数据集
  10. Matlab中断语句