标签:意义 close fun out 使用 提高 多线程 网络服务 检测
nodejs的特点总共有以下几点
下面是一道很经典的面试题,描述了node的整体运行机制,相信很多人都碰到了。这道题背后的原理就是nodejs代码执行顺序
setTimeout(function() {
console.log(‘4‘);
},0)
setImmediate(function() {
console.log(‘5‘);
})
let s = new Promise(function(resolve, reject) {
console.log(‘2‘);
resolve(true)
console.log(‘7‘)
})
s.then(function() {
console.log(‘3‘);
})
process.nextTick(function() {
console.log(‘6‘)
})
console.log(‘1‘);
// 我电脑的输出结果是 2、7、1、6、3、4、5
nodejs的运行机制: nodejs主线程主要起一个任务调度的作用。nodejs用一个主线程处理所有的请求, 将I/O操作交由底下的线程池处理;在所有主线程任务执行完成后,主线程处理事件队列。 所以在同步初始化代码执行完成后,nodejs会基于事件队列不停的做事件循环。事实上,nodejs运行环境 = 主线程(单线程,包括事件队列) + 线程池(工作线程池,执行其他工作-多线程)
注: 在主线程执行完和事件循环总共7个阶段,每一个阶段执行完都会调用一遍process.nextTick
回调,一遍microtaks
(promise);
主线程中,console.log
和promise
的new方法在初始化主线程中执行,他们俩个的输出时间按照先上后下的顺序输出,他们两个执行完后会立即执行主线程的process.nextTick
,然后执行promise.then
方法,然后是进入事件队列中执行setTimeout
和setImmediate
。因为setTimeout的
‘最少经过n毫秒后执行的脚本‘特性,导致无法确定setTimeout
和setImmediate
的执行先后顺序,但如果是在回调函数中,则必然setImmediate
先执行,因为事件循环的阶段中,setImmediate紧挨着回调函数之后执行,而setTimeout则在下次事件循环中执行。
IO操作: IO操作就是以流的形式,进行的操作,比如网络请求,文件读取写入。IO操作也就是input和output的操作。
阻塞IO: 在调用阻塞O时,应用程序需要等待IO完成才能返回结果。 阻塞IO的特点:调用之后一定要等到系统内核层面完成所有操作之后,调用才结束。 阻塞O造成CUP等待IO,浪费等待时间,CPU的处理能力不能得到充分利用。
非阻塞IO: 为了提高性能,内核提供了非阻塞IO,非阻塞IO跟阻塞IO的差别是调用之后会立即返回。阻塞IO完成整个获取数据的过程,而非阻塞IO则不带数据直接返回,要获取数据,还要通过描述符再次读取。非阻塞IO返回之前,node主线程可以用来处理其他事物,此时性能提升非常明显。
为什么node擅长I/O密集型,不擅长CPU密集型:因为node的I/O处理中主线程只负责转发,实际操作在其他线程及线程队列里完成,所以性能相对较高; 而CPU密集则要求node的主线程处理,这时候其余请求只能等待
我的理解: node的异步I/O分为两个阶段,第一个阶段是主线程调用线程池里的工作线程执行异步操作,主线程取回对应的描述符,存储下来,工作线程执行相关操作取回数据后存储下来,这一部分在主线程接收到请求后立即完成;第二个阶段在事件队列里完成,根据描述符去工作线程里去获取数据,以提升性能.
以下是对nodejs高并发的理解,nodejs的高并发体现在处理I/O的性能上,而不是CPU密集上,摘录自官网文档
让我们思考这样一种情况:每个对 Web 服务器的请求需要 50 毫秒完成,而那 50 毫秒中的 45 毫秒是可以异步执行的数据库 I/O。选择 非阻塞 异步操作可以释放每个请求的 45 毫秒来处理其它请求。仅仅是选择使用 非阻塞 方法而不是 阻塞 方法,就是容量上的重大区别。
Node 有两种类型的线程:一个事件循环线程和 k 个工作线程。 事件循环负责 JavaScript 回调和非阻塞 I/O,工作线程执行与 C++ 代码对应的、完成异步请求的任务,包括阻塞 I/O 和 CPU 密集型工作。 这两种类型的线程一次都只能处理一个活动。 如果任意一个回调或任务需要很长时间,则运行它的线程将被 阻塞。 如果你的应用程序发起阻塞的回调或任务,在好的情况下这可能只会导致吞吐量下降(客户端/秒),而在最坏情况下可能会导致完全拒绝服务。要编写高吞吐量、防 DoS 攻击的 web 服务,您必须确保不管在良性或恶意输入的情况下,您的事件循环线程和您的工作线程都不会阻塞。
通常意义上,I/O密集型活动,如网络I/O、文件I/O,DNS操作等通常建议放在对外提供网络服务的端口所在的服务内,剩下的诸如大内容的crypto,zlib,fs同步操作、子进程,JSON处理、计算等尽量另起node服务或者其他语言服务去进行,因为这些操作会影响到node的主线程的性能和安全性。
事实上,对于nodejs的相关理解更多的收获在于这里,nodejs官网指南的中文文档,以前有点粗心了
标签:意义 close fun out 使用 提高 多线程 网络服务 检测
原文地址:https://www.cnblogs.com/zhaowinter/p/11138555.html