前言
从小工到专家系列为从头开始学习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中传入的回调函数的目的.