刚开始了解Node感觉很吊,各种说高性能,可是一直不理解为什么单线程会比多线程快?为什么异步IO比非阻塞IO快?因此,本篇在阅读相关书籍后,根据自己的理解,整理此文,如有错误,仅代表理论不精,必当修改,以免误导他人。还请多多指正.....

关于阻塞IO和非阻塞IO

系统内核只有两种IO模式—— 阻塞IO和非阻塞IO。这里的IO可不仅仅是读取文件内容,而是更为广泛的概念。比如Socket啊,网络Socket,磁盘读取等等,这些相比于CPU计算都是很耗时的。

下图为阻塞IO的工作模式:

阻塞IO在需要获取数据进行IO操作时,CPU会等待,当读取完成后,再继续运行。那么很容易就能想到,如果读取很耗时,CPU就会长期处于阻塞状态,显然效率很低。

再看看非阻塞IO:

非阻塞IO在进行IO操作时,会直接返回。然后CPU该干嘛干嘛,只不过需要一定的策略来确定什么时间请求数据完成,这个时候就需要一些轮训策略了,比如select poll等等。那么这个也应该能想到,当有长期的IO操作,会白白执行大量的查询操作,效率也不高。(当然目前的系统内的非阻塞IO都是很高级的玩法,卤煮也没有仔细研究,就不献丑了)

异步IO与Node工作原理

通过上面两种典型的IO操作,很显然,一种理想的模型是,有IO操作时,系统去执行IO操作,CPU该干嘛干嘛,当请求数据完成后,就通知CPU继续执行刚才没有完成的工作。

Node就是利用了javascript的回调函数思想,实现这种工作模式。

那么为什么单线程的Node会效率很高呢?什么又是事件机制呢?

原来,一直说的单线程,都是javascript端的,Node底层还是使用c来实现,因此底层仍然是多线程的。只不过,Node基于不同的操作系统linux或者windows之上实现了一个封装层,用户执行的操作命令会转交给这个封装层,由它再去判断操作系统,进而调用相应平台的c代码。

有点跑题了,简单的说,就是Node只是表面暴露给用户的javascript代码是单线程的,底层还是多线程的。

说到事件机制,就要上图了!

简单的解释一下,当我们使用Node的时候,会在javascript触发一些命令调用方法,这些方法会被包装成一个对象,放入线程池,然后前面的方法就返回了,继续执行下面的JS代码。

线程池中采用多线程的方式执行,执行完的对象放入事件循环队列。

事件循环队列采用类似while(true)这种循环的方式,不断的查看是否有事件,并且读取是否包含回调,由于前面回调函数被包装到对象中,这里直接调用执行就可以了。

通过这三种阶段,就实现了 【 异步请求——>回调 】 的工作模式。

图解NodeJS【基于事件、回调的单线程高性能服务器】原理的更多相关文章

  1. 基于事件的 NIO 多线程服务器--转载

    JDK1.4 的 NIO 有效解决了原有流式 IO 存在的线程开销的问题,在 NIO 中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个 CPU 的处 ...

  2. C#中的异步调用及异步设计模式(三)——基于事件的异步模式

    四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: ·                 ...

  3. 基于epoll封装的事件回调miniserver

    epoll技术前两节已经阐述过了,目前主要做一下封装,很多epoll的服务器都是采用事件回调方式处理, 其实并没有什么复杂的,我慢慢给大家阐述下原理. 在networking.h和networking ...

  4. .NET - 基于事件的异步模型

    注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...

  5. Monad、Actor与并发编程--基于线程与基于事件的并发编程之争

    将线程.事件.状态等包装成流的源. 核心:解决线程的消耗和锁的效率问题. Java和Node.js可以说分别是基于线程和基于事件的两个并发编程代表,它们互相指责瞧不起对方,让我们看看各种阵营的声音: ...

  6. 关于”nodejs基于事件驱动”的思考

    刚想通是怎么回事. 以页面上的js为例,你可以给多个标签注册事件回调,然而,无论给 多少个标签 注册 多少个事件回调,这些回调都只会等待自己命中注定的那个事件,在执行上都不会彼此影响!!! 再想一下w ...

  7. 一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库 RxJava,相当好

    https://github.com/ReactiveX/RxJava https://github.com/ReactiveX/RxAndroid RX (Reactive Extensions,响 ...

  8. nodejs触发事件的两种方式

    nodejs触发事件的两种方式: 方式之一:通过实例化events.EventEmitter //引入events模块 var events = require('events'); //初始化eve ...

  9. 基于Spring + Spring MVC + Mybatis 高性能web构建

    基于Spring + Spring MVC + Mybatis 高性能web构建 一直想写这篇文章,前段时间 痴迷于JavaScript.NodeJs.AngularJs,做了大量的研究,对前后端交互 ...

随机推荐

  1. URAL 1430 Crime and Punishment

    Crime and Punishment Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u ...

  2. Python基本语法初试

    编程环境: win7旗舰版 Python 3.2.2(default, Sep  4 2011,09:51:08) 代码来源:(Python菜鸟) 代码内容: Python基本的输出语句print(& ...

  3. C++find函数

    头文件 #include <algorithm> 函数实现 template<class InputIterator, class T> InputIterator find ...

  4. EntityFramework6 快速入门教程

    EntityFramework6 快速入门教程 不得不说EF在国内实在是太小众,相关的技术文章真实屈指可数,而且很多文章都很旧了,里面使用的版本跟如今的EF6差别还是比较大.我刚开始弄这个的时候真是绕 ...

  5. 离散化+线段树 POJ 3277 City Horizon

    POJ 3277 City Horizon Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18466 Accepted: 507 ...

  6. codeforces 711C C. Coloring Trees(dp)

    题目链接: C. Coloring Trees time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  7. POJ 1984 Navigation Nightmare

    并查集,给n个点和m条边,每条边有方向和长度,再给q个询问,第i个询问查询两个点之间在Ti时刻时的曼哈顿距离(能连通则输出曼哈顿距离,否则输出-1) 这题跟Corporative Network 有点 ...

  8. 最严谨的校验email地址的正则表达式

    通用 (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0 ...

  9. uGUI练习(六) ScrollView

    练习目标 练习uGUI的滑动组件 一.相关组件 ScrollRect Mask Grid Layout Group Scrollbar 二.步骤 1.创建一个Panel,命名为ScrollRect,添 ...

  10. Android Parcelable和Serializable的区别,androidparcelable

    本文主要介绍Parcelable和Serializable的作用.效率.区别及选择,关于Serializable的介绍见Java 序列化的高级认识. 1.作用 Serializable的作用是为了保存 ...