最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 《深入浅出Nodejs》总结、记录(一)

    正文概述 掘金(阿玉君_)   2021-05-02   613

    node简介

    node是一个基于事件驱动来实现非阻塞I/O的服务器。 node结构和chrome十分相似,它们都是基于事件驱动的异步架构,浏览器通过事件驱动来进行页面交互、Node通过事件驱动来服务I/O。

    node应用场景

    因为node是异步I/O,所以处理I/O密集型的任务是毋庸置疑的(I/O密集型任务包括文件操作、网络通信等),node利用事件循环的处理能力,而不是启动每一个线程为每一个请求服务,资源占用极少。而cpu密集型的计算任务主要得益于V8引擎的深度优化。

    node为什么会是单线程?

    单线程最大的好处是不用像多线程编程那样处处在意状态同步问题,这里没有死锁的存在,也没有线程上下文切换所带来的性能开销。

    单线程所带来的缺点?

    • 无法利用多核cpu
    • 错误会引起整个应用退出,应用的健壮性值得考验
    • 大量计算占用CPU导致无法继续调用异步I/O

    像浏览器端js与UI公用一个线程一样,node端cpu长时间占用也会导致后续的异步I/O无法调用,已完成的异步I/O函数也会得不到及时执行。
    后来node出现了子进程child_process,遇到大量计算性的任务,可以将计算分解到各个子进程,然后通过进程间的通信来传递结果。

    异步I/O

    异步I/O与非阻塞I/O

    异步与非阻塞听起来像是一回事,就实际效果而言,异步与非阻塞都能打到并行的目的。但是从计算机内核而言,同步/异步和阻塞/非阻塞实际上是两回事。
    操作系统对于I/O只有两种方式,阻塞和非阻塞。 阻塞I/O造成CPU等待I/O,浪费时间等待,CPU的处理能力得不到充分利用。 非阻塞I/O返回之后,CPU可以处理其他事务,但是由于此时的I/O并没有完成,获取的数据并不是我们希望的数据,为了获取完整的数据,应用程序需要重复调用I/O来确认是否完成,这种重复调用判断的技术叫做轮询。

    node中的异步I/O——事件循环

    在node进程启动时,会有一个类似于while(true)的循环,每执行一次循环体的过程我们称之为tick。每个tick的过程就是检查是否有事件需要处理,如果有,就取出事件及其相关的回调函数。如果存在相关的回调函数,就执行它们。然后进入下个循环,如果不再有事件处理,就退出进程。

    node中的异步I/O——观察者

    在每个tick的过程中,每个事件循环有一个或多个观察者,而判断是否有事件要处理就的过程就是向这些观察者询问。在Node中,事件主要来自于网络请求、文件操作等,这些事件对应的观察者有网络观察者、文件I/O观察者等,观察者将事件进行了分类。

    nodejs中的异步I/O是如何实现的?(与浏览器中的异步有什么不同

    nodejs中的异步I/O有I/O线程池的参与。node启动时,同时会有一个事件循环启动,事件循环中有一个I/O观察者,观察是否有I/O调用结束。node中发起一个异步I/O操作时,会先封装一个请求对象,将I/O操作的参数和回调函数封装进这个对象中,然后将这个对象传递给I/O线程池,I/O线程池收到对象,会先判断线程是否可用,若是可用,执行对象中的I/O操作,将执行完的结果也放入请求对象中,然后通知I/O观察者调用完成,此时线程池回归可用状态。I/O观察者能拿到请求对象,取出请求对象中的回到函数和执行结果,执行回调函数。此时一个异步I/O操作完成。

    非I/O的异步API

    在node中还存在与I/O无关的API,它们分别是setTimeout、setInterval、setImmediate、process.nextTick以及setImmediate
    setTimeoutsetInterval与浏览器中一致,但与异步I/O相比较就是没有I/O线程池的参与。每次setTimeoutsetInterval创建的定时器会被插入到定时器观察者内部的一个红黑树中,每次Tick执行时,会从该红黑树中取出定时器对象,检查是否超过定时时间,如果超过,就形成了一个事件,回调函数立即执行。
    每次调用process.nextTick()方法,只会将回调函数放入队列中去,在下一轮Tick时取出执行。与setTimeoutsetInterval相比,process.nextTick()性能更高效,因为定时器需要动用红黑树、创建定时器对象和迭代等操作。
    setImmediateprocess.nextTick()十分类似,都是讲回调函数延迟执行,但是也有一些细微的差别。process.nextTick()中回调函数优先级要高于setImmediate。原因在于事件循环对于观察者的检查是有先后顺序的。process.nextTick()属于idle观察者,setImmediate属于check观察者。在每一轮循环检查中,idle观察者要先于I/O观察者,I/O观察者先于check观察者。process.nextTick()的回调函数保存在一个数组中,setImmediate的回调函数保存在链表中。process.nextTick()每轮循环会把数组中的回调函数全部执行完,setImmediate每轮循环中执行链表中的一个回调函数。

    模块机制Commonjs

    模块定义

    上下文中提供·require方法来引入外部模块,提供exports对象用来导出方法或者变量,并且是唯一到出口。在模块中,还有一个module对象,代表模块自身,exports就是module的一个属性。一个文件就是一个模块。
    node中模块分为两类,一类是node提供的模块,称为核心模块。另一类是用户编写的模块,称为文件模块。

    模块定义的意义

    将类聚的方法或变量等限定在私有的作用域中,同时支持引入和导出功能以顺畅的连接上下游依赖。Commonjs这套导出出入机制使得用户完全不必考虑变量污染

    引入模块经历的步骤

    1. 路径分析
    2. 文件定位
    3. 编译执行
    • 核心模块在node源代码的编译过程中,编译进了二进制执行文件。在node进程启动时,核心模块就被直接加载进内存,所以文件定位和编译执行这两步直接省略,并且路径分析中优先判断,所以加载速度最快。
    • 文件模块在运行时动态加载,需要走完成的三个流程,所以加载速度要慢一些。

    浏览器会缓存静态文件脚本以提高性能、而node会缓存编译后的对象以提高性能。
    不论是核心模块还是文件模块,require()引入时对相同模块都是先从缓存中加载,这是第一优先级的,只不过核心模块的缓存检查先于文件模块。
    从缓存中加载的优化策略可以使二次引入时不需要路径分析、文件定位和编译执行,大大提高效率。

    模块编译

    1. .js文件 通过fs模块同步读取文件然后编译执行
    2. .node文件 这时通过c/c++编写的扩展文件,通过dlopen()加载然后编译生成的文件
    3. .json文件 通过fs模块同步读取文件后,用JSON.parse解析返回的结果。

    javascript模块的编译

    在编译js的过程中,Node对获取的js文件内容进行头尾包装。也就是将原本的js代码用一个函数包装了起来。

    (function(exports,require,module,__filename,__dirname){
        var Math = require('math');
        exports.area = function(radius){
            return Math.PI*radius
        }
    });
    

    内存控制

    垃圾回收机制

    V8对象分为新生代对象(存活时间比较短)和老生代对象(存活时间比较长)。
    新生代对象采用复制移动的方式实现垃圾回收,新生代内存的空间分为两个部分,一个是From空间,另一个是to空间。进行对象分配时,先在From空间进行分配,当进行垃圾回收时,会将存活对象复制到To空间,然后将From所有对象清空,在将To空间的对象复制到From空间,最后清空To空间。
    在进行新生代内存垃圾回收时,会检查对象是否已经经历过一次垃圾回收,若是,会将这个对象升级为老生代对象。同时,也会检查To空间内存使用是否超过25%,若是,会将剩余的对象设置为老生代对象。
    老生代对象采用标记清除法,在标记阶段遍历所有堆中的对象,并标记活着的对象,在随后的清楚阶段,只清除没有被标记的对象。
    标记清除法有一个问题就是进行过一轮垃圾回收后,内存空间会是不连续的状态,这种内存碎片会对后续内存分配造成问题,所有出现了标记整理法,在回收阶段将活着的对象往一端移动,移动完成直接清理掉边界内存。


    起源地 » 《深入浅出Nodejs》总结、记录(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元