20分钟理解Node.js模型概念
名字
Node.js
是唯一正确的名字。它不是一门语言,也不是一种框架,它是:
- Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
- Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
基于 Chrome V8 引擎
我们所用JS写的Node.js代码,它是通过V8引擎(C++代码)来运行的,而里边涉及到对操作系统的调用,这一部分就会由v8引擎帮我们转发到我们的操作系统层面,从操作系统层面得到返回结果之后,再通过v8引擎返回到 JS 里边去。
在 Node.js 里运行 JavaScript 跟在 Chrome 里运行 JavaScript 有什么不同?
-
Node.js 没有浏览器 API ,即 document ,window 等。
-
加了许多 Node.js API 。
-
对于开发者来说,Node.js :
- 你在 Chrome 里写 JavaScript 是在控制浏览器。
- 而 Node.js 让你用类似的方式,控制整个计算机
事件驱动
概念
事件循环器(Event Loop)是一个程序结构,用于等待和发送消息和事件。事件驱动编程的代码核心就是事件循环器,在Linux下推荐使用epoll实现。
Event loop 和 event queue 一起工作, event queue就只是一个单纯的放置JavaScript functions的队列。我们把在event queue里面的 functions 叫做 events,当libuv完成任务, runtime会把关联的callback放到event queue,event loop在event queue和JavaScript engine中间, event loop的工作就是从event queue拿event放到JavaScript engine去执行
event loop遵守以下规则放event:
- JavaScript Engine执行js代码时, event loop会暂停 -> 单线程
- 如果JavaScript Engine有空, event loop就会把在event queue的第一个event放到JavaScript Engine,JavaScript Engine开始执行
- 当涉及到I/O操作的时候,Node.js会开一个独立的线程来进行异步I/O操作,操作结束以后将消息压入event queue
事件源
事件源可以是任意一个继承自 Node.js 内置模块 events
的EventEmitter类的实例。
const { EventEmitter } = require('events')
class MyModule extends EventEmitter{
constructor(){
super
}
}
继承后,实例上会有多个与事件相关的属性。其中, _events
属性指向一个空对象,用于缓存事件类型和事件处理程序。同时,实例也拥有了EventEmitter原型上的方法,emit
on
等。
非阻塞式 I/O
概念
- I/O 即 Input/Output,一个系统的输入和输出
- 阻塞 I/O 和非阻塞 I/O 的区别就在于系统接收输入再到输出期间,能不能接收其他输入
进程
进程的五种状态:
阻塞的本质就是利用CPU中断,将进程挂起,并让出时间片(相当于告诉计算机,下一轮执行我不参与了),而唤醒阻塞的本质是:将进程的状态置为Runnable(相当于告诉计算机,下一轮我可以执行了)
非阻塞I/O就是好,阻塞I/O就全是缺点?
阻塞I/O优点:代码好理解,且阻塞时不会占用系统资源;阻塞IO缺点:高并发场景需要较高的线程数,资源占用大,且线程切换有成本
非阻塞I/O优点:操作不阻塞线程,读不到就返回null或者其它失败标识。所以,后面就需要持续重试,是需要搭配一定的编程手段去完善整个做法的,最简单的做法就是启个线程,不停的去检查有没有读到,这个就是I/O多路复用。
课外知识
转载自:https://juejin.cn/post/7238065836341887034