图解NodeJS【基于事件、回调的单线程高性能服务器】原理
刚开始了解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【基于事件、回调的单线程高性能服务器】原理的更多相关文章
- 基于事件的 NIO 多线程服务器--转载
JDK1.4 的 NIO 有效解决了原有流式 IO 存在的线程开销的问题,在 NIO 中使用多线程,主要目的已不是为了应对每个客户端请求而分配独立的服务线程,而是通过多线程充分使用用多个 CPU 的处 ...
- C#中的异步调用及异步设计模式(三)——基于事件的异步模式
四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: · ...
- 基于epoll封装的事件回调miniserver
epoll技术前两节已经阐述过了,目前主要做一下封装,很多epoll的服务器都是采用事件回调方式处理, 其实并没有什么复杂的,我慢慢给大家阐述下原理. 在networking.h和networking ...
- .NET - 基于事件的异步模型
注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...
- Monad、Actor与并发编程--基于线程与基于事件的并发编程之争
将线程.事件.状态等包装成流的源. 核心:解决线程的消耗和锁的效率问题. Java和Node.js可以说分别是基于线程和基于事件的两个并发编程代表,它们互相指责瞧不起对方,让我们看看各种阵营的声音: ...
- 关于”nodejs基于事件驱动”的思考
刚想通是怎么回事. 以页面上的js为例,你可以给多个标签注册事件回调,然而,无论给 多少个标签 注册 多少个事件回调,这些回调都只会等待自己命中注定的那个事件,在执行上都不会彼此影响!!! 再想一下w ...
- 一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库 RxJava,相当好
https://github.com/ReactiveX/RxJava https://github.com/ReactiveX/RxAndroid RX (Reactive Extensions,响 ...
- nodejs触发事件的两种方式
nodejs触发事件的两种方式: 方式之一:通过实例化events.EventEmitter //引入events模块 var events = require('events'); //初始化eve ...
- 基于Spring + Spring MVC + Mybatis 高性能web构建
基于Spring + Spring MVC + Mybatis 高性能web构建 一直想写这篇文章,前段时间 痴迷于JavaScript.NodeJs.AngularJs,做了大量的研究,对前后端交互 ...
随机推荐
- Linux traceroute
一.简介 traceroute 通过发送 TCP 数据包向目标端口进行探测,以检测源到目标服务器的整个链路上相应端口的连通性情况. 二.语法 -n 直接使用IP地址而非主机名称(禁用 DNS 反查 ...
- quick sort java version
import java.util.Random; public class test { public static void main(String[] args) { int[] arr= gen ...
- 如何用ZBrush雕刻出栩栩如生的头发(二)
之前的ZBrush教程教大家使用SubTool为模型添加了杂乱头发效果的两种雕刻手法,今天将继续介绍其他方法对模型头发雕刻技巧和细节进行讲解.文章内容仅以fisker老师讲述为例,您也可以按照自己的 ...
- Centos源码安装Python3
CentOS7默认安装了python2.7.5,当需要使用python3的时候,可以手动下载Python源码后编译安装. 下载python(https://www.python.org/ftp/pyt ...
- AC日记——神奇的幻方 洛谷 P2615(大模拟)
题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...
- HTML5之应用缓存---manifest---缓存使用----HTML5的manifest缓存
相信来查这一类问题的都是遇到问题或者是初学者吧! 没关系相信你认真看过之后就会知道明白的 这是HTML5新加的特性 HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连 ...
- JMeter学习(六)集合点
JMeter也有像LR中的集合点,本篇就来介绍下JMeter的集合点如何去实现. JMeter里面的集合点通过添加定时器来完成. 注意:集合点的位置一定要在Sample之前. 集合点:简单来理解一下, ...
- sqlzoo.net刷题3
Find the continents where all countries have a population <= 25000000. Then find the names of the ...
- Converting a Polygon ZM shape file to a regular Shape Polygon
from:http://blog.csdn.net/qb371/article/details/8102109 Locate the following tool - ArcToolbox > ...
- kvm虚拟化管理平台WebVirtMgr部署-完整记录(安装ubuntu虚拟机)-(5)
之前介绍了在webvirtmgr平台下创建centos,windows server 2008的虚拟机,今天说下创建ubuntu虚拟机的过程. (1)首先下载ubuntu16.04的iso镜像放到/u ...