Nodejs从小工到专家系列(一)

567 查看

前言

从小工到专家系列为从头开始学习Nodejs,但它并不是教程,我会整理一些应该特别注意或深入理解的知识点,当然也会涉及常用的库,比如Express,mongoose,bluebird..

Nodejs特点:

单线程

优点:

  • 没有死锁存在

  • 没有线程上下文交换所产生的性能开销

缺点:

  • 无法利用多核

  • 错误会引起整个应用退出,健壮性不高

  • 大量计算占用CPU导致无法继续调用异步I/O

解决方案:

  • 引入child_process,大量计算时可以将计算分发到子进程,缓解压力

  • 进程之间通过事件消息传递结果

跨平台

兼容Windows和*nix.在操作系统与Node上层模块之间构建一层平台层架构,即libuv

效率高

  • V8引擎

V8是谷歌开发的,目前公认最快的 Javascript 解析引擎,libuv 是一个开源的、为 Node 定制而生的跨平台的异步 IO 库。

高性能

采用事件循环,而不是为每个连接分配一个线程

应用场景

  • 对实时和并发有很高要求的,比如游戏,聊天等等

非阻塞I/O

操作系统内核对于I/O只有两种方式:阻塞与非阻塞.在调用阻塞IO时,应用程序需要等待I/O完成才能返回结果.

阻塞I/O造成CPU等待I/O,浪费等待时间,CPU的处理能力不能得到充分利用.为了提高性能,内核提供了非阻塞I/O.非阻塞I/O会在调用后立即返回.

上面的立即如何理解呢?

因为阻塞I/O完成了整个获取数据的过程,而非阻塞I/O则不带数据直接返回,要获取数据,还需要通过文件描述符再次读取.

  • 文件描述符类似于应用程序与系统内核之间的凭证.如果应用程序需要进行I/O调用,需要先打开文件描述符,然后在根据文件描述符去实现数据的读写

但非阻塞I/O存在些问题,它立即返回的并不是业务层期望的数据,而仅仅是当前调用的状态.为了获取完整的数据,应用程序需要重复调用I/O操作来确认是否完成.这种重复调用判断操作是否完成的技术叫做轮询

异步I/O

事件循环

在进程启动时,Node会创建一个类似与while(true)的循环,它的作用就是产看是否有事件待处理,如果有就取出并处理,直到没有就退出进程.

观察者

如何知道是否有事件待处理呢,就引入了观察者.再Node中观察者包括文件I/O观察者和网络观察者等.相当于一个探哨的.

请求对象

当我们要从自己写的js到系统进行调用,会经历一个过程js->Node核心模块->C++内建模块->libuv->系统,那么传递参数信息就会利用一个请求对象,包括回调函数也在里面.

请求对象是非常重要的中间产物,所有的状态都保存再这个对象中,包括送入线程池等待执行及I/O操作完毕后的回调处理.

执行回调

组装好请求对象,送入I/O线程池等待执行,实际上完成了异步I/O的第一部分,回调通知是第二部分.I/O观察者回调函数的行为就是取出处理后返回的结果,以此达到调用JavaScript中传入的回调函数的目的.