Node.js——事件驱动、单线程、非阻塞I/O

75 阅读2分钟

什么是node

node是一个基于v8引擎的服务端javascript运行时环境,主要有标准库、中间层和底层库三个部分组成。

标准库: 提供了开发人员能够直接进行使用的API

中间层: 是标准库和底层库之间的桥梁,因为标准库是javascript代码,底层库是C/C++,它们之间无法直接通信,通过中间层,底层实现的C/C++暴露给javascript,同时将javascript传给V8进行解析,然后通过libuv进行事件循环调度

底层库: 是node运行的关键,由C/C++实现,主要包括四个部分:

  • V8引擎:Google开发的一套为Javascript提供在非浏览器端运行的环境
  • libuv:是C语言实现的一套异步功能库,为Node.js提供了跨平台,线程池,事件池,异步I/O 等功能
  • C-ares:DNS解析
  • http-parser、openssl、zlib:负责解析http响应、加解密、压缩等功能

架构图:

事件驱动

node.js的事件驱动模式是其核心设计理念之一。在node中,几乎所有的I/O事件都是异步的,它基于事件循环(Event Loop)机制,在发起一个异步I/O时,不会等待结果返回,而是继续执行后面的程序,等到I/O处理完了,事件循环会将对应的回调函数取出来执行。

通过一个例子,了解下事件驱动编程:

// 引入events模块
const EventEmitter = require('events')
// 创建事件发射器实例
const emitter = new EventEmitter()
// 触发事件的回调函数函数
function callBack () {
  console.log('myEvent事件被触发了')
}
// 监听myEvent事件
emitter.on('myEvent', callBack)
// 触达myEvent事件
emitter.emit('myEvent')

单线程

node.js本身不是单线程的,我们常说的node是单线程是指用于执行用户代码的Javascript主线程是单线程的。

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

单线程的弱点是无法利用多核CPU,错误会引起整个应用退出,大量计算占用CPU导致无法继续调用异步I/O。

非阻塞I/O

在node.js中,所以I/O都是非阻塞的,当某个I/O操作发生时,不是等待其执行完才进入下一个步骤,而是立即执行后面的代码。当某个I/O执行完成后,通过事件的形式通知主线程来执行回调。因此,Node擅长I/O密集型的应用场景。