Node.js
- 不是web框架
- Node.js并不是web后端框架,不能把它跟Flask或Spring对比
- 不是编程语言
- Node.js并不是后端的JS,不能把它与Python或PHP做对比
- Node.js是一个平台
- 它将多种技术组合起来,让JavaScript可以调用系统接口、开发后端应用
- 用到了下面这些技术
bindings
- 背景
- C/C++实现了一个http-parser库,很高效
- JS无法直接调用这个库,需要一个中间的桥梁
- bindings
libuv
背景
- 每个系统上的异步I/O都不一样
- FreeBSD系统上有kqueue
- Linux系统上有IOCP
- Ryan为了一个跨平台的异步I/O库,开始写libuv
-
功能
可以用于TCP/UDP/DNS/文件等的异步操作
V8
功能
- 将JS源代码变成本地代码并执行
- 维护调用栈,确保JS函数的执行顺序
- 内存管理,为所有对象分配内存
- 垃圾回收,重复利用无用内存
-
注意
V8不提供DOM API
- V8执行JS是单线程的
- 可以开启两个线程分别执行JS
- V8本身是包含多个线程的,如垃圾回收为单独线程
- 自带event loop但Node.js 基于 libuv 自己做了一个
Event Loop
Event
- 计时器到期了
- 文件可以读取了,读取出错了
- socket有内容了,关闭了
-
Loop
loop就是循环,比如while(true)循环
- 由于事件是分优先级的,所以处理起来也是分先后的
- 所以Node.js需要按顺序轮询每种事件
- 这种轮询往往都是循环的,1->2->3->1->2->3
-
举例
三种不同的事件
- setTimeout(f1,100)
- fs.readFile(‘/1.txt’,f2)
- server.on(‘close’,f3)
- 如果同时触发,Node会怎么办
- 肯定会有某种顺序(优先级)
- 这种顺序应该是人为规定的
Event Loop
- 操作系统可以触发事件,JS可以处理事件
-
顺序示意图
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
重点阶段
timers检查计时器
- poll轮询,检查系统事件
- check检查setImmediate回调
-
注意
大部分时间,Node.js都停在poll轮询阶段
- 大部分事件都在poll阶段被处理,如文件、网络请求