接触 node.js 有好几年了,也开发了好几个项目了;但每次提起 node.js,始终不敢说自己入门了,归其原因,大概就是如下所示
为了进一步加强理解,系统的梳理相关知识以作备忘,本节将从以下几个方面介绍 node.js
Node.js 单线程高并发的特性非常适合用来创建后端服务;虽然但是,好像不会使用 Node.js 根本不影响我写前端页面嘛~。
no no no,作为一个新时代的三有
前端,要本着知其然并知其所以然的精神彻底掌握 Node.js,因为它不仅仅是用来写后端,更重要的用途是提升我们项目工程化和效率。
你自己也会写 npm 包、脚手架、打包脚本了,是不是很受诱惑,嘿嘿…
Node官网对其进行了简单的不能再简单的描述
Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。
翻阅官网教程,大致对其概念和特性有了一些认识:
同样是解析 JavaScript,为啥 Node.js 与浏览器的功能差别这么大?
在 Node.js 之前,JavaScript 主要运行在浏览器宿主环境中,主要是操作 DOM、BOM,浏览器提供了 document、window 等对象;
Node.js 则允许在服务端运行 JavaScript,不具有浏览器才有的 window、document 等对象,主要是操作磁盘文件、搭建 http 服务等等等等…
这么牛逼?提供各种模块,还能在各大平台运行的飞起,这是我了解的 JavaScript?其本质不是 JavaScript 有多牛逼,而是它封装了许多强大的依赖,以下是 Node 源码的依赖列表
最典型的依赖就是 v8 和 uv
上图是 libuv 大致的结构,很明显,Node.js 的网络 I/O、文件 I/O、DNS 操作、还有一些用户代码都是在 libuv 工作的
libuv 的存在,使得 Node.js 可以是单线程的。每当有 I/O 请求发生时,node 就会扔给 libuv,由 libuv 为该请求分配给不同的工作线程(libuv 默认维护 4 个线程供 Node 调用,可以通过 UV_THREADPOOL_SIZE 环境变量在 Node 启动时设置,为了性能,不能超过 128 个),同步阻塞性的执行,执行完成后将回调函数放入事件队列中。
而 node 则不会管这个 I/O 的操作过程,继续执行主线程上的事件,只需要在该请求返回回调时在处理即可,从而实现非阻塞性的异步 I/O 处理。
与 JavaScript 一样,Node 是单线程,它将阻塞性的操作丢给 libuv 提供的线程池。
单线程的优点:
服务器内存受限
的情况下,具有更好的高并发单线程的缺点:
概念:线程是进程内的最小执行单元。一个进程可以有一个或多个线程。所有线程共享该进程的地址空间和资源。
进程与进程之间相互独立,通讯困难;而线程与线程则共享进程的资源,通讯简单;
Node.js 本身运行在一个进程中,当我们说 Node.js 是单线程时,是指它在这个进程中只使用一个线程来执行 JavaScript 代码
Node.js 只有一个主线程,是单线程;但并不是说 Node 只支持单线程;如果想要创建新的线程,可以使用 Node.js 内置的 Worker threads 模块
如果想要创建新的进程,可以使用 Node.js 内置的 Cluster 、Child process 模块。
传统的服务端语音中(如 Java),每一个客户端连接都会为其创建一个新的线程,而每个线程都需要一定的内存(1~2M),受服务器内存限制,成为了高并发连接的瓶颈。
Node.js 则只有一个线程,大大的节省了服务器内容,它通过为每一个用户连接在 Node.js 内部,触发一个事件,Node.js 高并发的特性使得它在构建在线聊天、秒杀、抢购等应用时具有非常大的优势.
当然,这是建立在内存受限的情况下,如果你有足够大的服务器内存;那么传统的服务端语言将拥有更快的响应速度,Node 的事件循环机制将可能出现等待,即主线程有同步阻塞任务,事件循环将被阻塞
Node.js 通过异步回调来处理,那么 Node 如何知道请求或操作完成了添加回调;又是如何执行回调的?这是由于 Node.js 的另一特性:事件循环机制
,主线程通过 Event Loop 事件循环触发的方式来运行程序
注意,Node.js 的事件循环与浏览器下 JavaScript 的事件循环机制是不一样的,具体参考浏览器事件循环 VS Node.js 事件循环
好消息:今天周三了
坏消息:今天才周三
按道理,我没记错的话,朋友,今天应该是周五的吧~