Open gongmw opened 4 years ago
我们学习掌握一门新技术时候,第一步应当从它的官方文档开始认知,打开Node.js官方文档可以看到比较显眼的一句话是。
Node.js是建立在Chrome V8 上面的一个JavaScript运行环境
通俗点解释: js属于一种脚本性语言,然而脚本语言运行需要一个解析器来解析,对于我们原来写的js代码大部分都是运行在网页上,所以浏览器本身就担当了解析器的角色。而现在对于独立运行在服务器的js代码,node就属于那个解析器。
V8属于Google Chrome 浏览器的一个高性能引擎,可以直接将JavaScript编译为本地机器代码,而其他的语言如PHP和Ruby,Java每次访问时都必须通过解释器运行。
node的诞生到目前也走过了10多年,一路走来辉煌过、质疑过、突围过、到目前,可谓天生我材必有用,千金散尽还复来。
所以笔者自己做了一个时间轴图来和大家一起见证下node在历史洪流中比较重要的时刻。
此外我还收集整理了两篇关于NodeJS创始人Ryan Dahl的访谈录,一篇是10年前的 Ryan Dahl的访谈和一篇近期对Ryan Dahl的访谈, 虽然内容不是很多关于NodeJs技术层面的问题和教程,但记者对Ryan Dahl提的一些有趣的问题,和Ryan Dahl的回答会让你感觉很有趣也会让你对Node有一些不一样的见解,如果大家对访谈录感兴趣的可以关注我的微信公众号一起学Node中查看,可以带你了解NodeJs的前世今生。
我们使用node可能听到最多的几个特性就是
Node JS的应用程序,是使用单线程以及事件循环体系结构组合,来处理客户端请求的,但实际上我们要明白不要误解的一点它只是主事件循环是单线程的, 其他的比如I / O处理相关的操作是有单独的线程去处理,因为Node JS中很多的I / O API在设计上本就是异步/非阻塞的,为了就是更方便适应主事件循环。
为此笔者也做了两个小图给大家描述下Node与传统服务器端环境之间的区别,可以看到不一样的点。
图1:
图二:
图1中
图2中
当然关于单线程多线程的问题知识点是有很多内容扩展的,大家可以关注后续章节为大家分享。
说到非阻塞我们可能想到的就是和阻塞概念放在一起讨论
阻塞
阻塞的定义是指在 Node.js 程序中,其它 JavaScript 语句的执行,必须等待一个非 JavaScript 操作完成。这是因为当阻塞发生时,事件循环无法继续运行 JavaScript。 阻塞执行的方法都为同步执行执行,例如我们常见的文件读取案例就是典型的同步读取操作。
const fs = require('fs'); const data = fs.readFileSync('/file.txt');
非阻塞
前面提到当阻塞发生时,事件循环无法继续运行 JavaScript。在非阻塞时当任何请求发送到服务器时,它不会将发送过来请求排队缓存。接受请求后并开始执行(如果它阻塞了操作),然后将其发送到对应的工作线程区域进行处理,并在代码执行完成后立即为该线程注册一个回调,然后触发相同的回调并进入事件队列,之后再次由事件循环处理响应发送到相应的客户端,在这里它几乎不会阻塞。
有朋友刚开始可能会认为异步和非阻塞差不多(我当时也是这么认为的),这种想法是错误的。
异步和非阻塞虽然都达到了我们并行 I/O 的目的。但是从计算机内核 I/O 而言,异步 / 同步和阻塞 / 非阻塞实际上是两回事
前两个是比较好容易理解, Event Loop这个特性很少有人说可以完完全全搞明白它到底是怎么运转的,更多的是大家通过一些优秀文章和讲解以及一些经验来理解,Event Loop也是贯穿这node的核心,熟悉理解对于node学生有大有帮助,在描述之前先和大家分享一点很多人对此的一些误解点。
误解点:有一个主线程在运行用户的js代码,另一个线程运行事件循环。每次异步操作发生时,主线程将工作移交给事件循环线程,一旦完成,事件循环线程将等待主线程以执行回调
实现情况:只有一个线程执行js代码,就是事件循环运行的线程,回调的执行是由事件循环完成的
误解点:异步操作(如处理文件系统、执行出站HTTP请求或与数据库通信)都是加载到libuv提供的线程池中进行执行处理
实际情况: Libuv在默认情况下创建一个线程池,其中有四个线程可以将异步工作转移到其中,然而如今的操作系统已经为许多I/O任务都提供了异步接口,在一定情况下,libuv将使用这些异步接口进行调用,避免使用线程池,只有在没有其他方法的情况下,线程池才会用于异步I/O
libuv 是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的 API
误解点:事件循环连续地遍历异步任务进行先进先出,并在任务完成时执行回调
现实情况:虽然涉及到类似队列的结构,但事件循环不会遍历并处理堆栈,作为事件循环是一组以循环方式处理特定任务的阶段
这几个是很多同学比较容易误区的几个点, 看到官方的一些描述是:
事件循环是 Node.js 处理非阻塞 I/O 操作的机制——尽管 JavaScript 是单线程处理的——当有可能的时候,它们会把操作转移到系统内核中去。
看了这些话可能不会所动,说的还是太官方了语言描述太简单了,就像我们的新闻描述一样字越少说明事越不简单,先不要急,再来看看对于事件循环机制的整个周期阶段说明,官方给出了一张图
从上图中大致可看出 事件循环的流程和大概:
数据输入–>轮询阶段(poll)–>检查阶段(check)–>关闭事件回调阶段(close callback)–>定时器检测阶段(timer)–>I/O 待定回调阶段(pending callbacks)–>闲置阶段(idle, prepare)–>轮询阶段(反复循环)
关于此知识点更详细的内容可查看官方文档
大家想深入了解的可以关注后续文章,在核心篇里会讲解扩展更多node相关知识点和实践
在看到两个比较好的动画图解释浏览器和node的事件循环的流程对比
浏览器的: (来源:Fundebug)
node的: (来源:Fundebug)
知道了它的诞生、特性、原理,下面我们来看看它的一些应用和不足,毕竟技术只有落地才是真理,不然说的再多都是白搭
还有很多就不例举了,这些领域不是说是node专属的只是相对于其他从各方面考虑要适合一些
阿里:光一个egg.js就是最好的说明了
腾讯:微信小程序,云服务部分功能
网易:pomelo框架
Uber:每天使用Node处理20亿个远程过程调用(Remote Procedure Call,RPC)
PayPal:根据Node.js at PayPal,使用Node.js之后,应用开发速度提高了2倍;代码量减少了33%;文件数目减少了40%,并且,每秒处理的请求数增加了2倍,接口的请求时间减少了35%
像微软谷歌这些公司多年前就加入基金会了
因为这些头部公司的接入使用说明node的发展还是很成功的,但技术只有通过多个方面综合考虑如人力成本 学习成本等才能定下来,node发展迅速与采用js语言为基础学习成本低使用人数多,并和强大的npm社区密不可分,但这些不能掩盖它的一些缺点导致npm包的质量参差不齐。
只有正面node的一些缺点才可以更理性的看待它,就像TJ在决定离开node的时候说的,如果是web开发他还是会采用node,只不过他要开始转向分布式系统的开发了,所以不适合了。
计算密集型应用 如果非要把Javascript和C去拼计算性能,结果可想而知。
内存控制 把js和java比较复杂数据类型定义的话,也是不明智的。因为js的面向对象是基于JSON的,而java是直接使用内存结构。所以,通过JSON序列化和反序列的过程控制内存,js在开始就已经败了。
静态服务器,I/O密集应用固然是node的优势,但是你非要把它和Nginx这种专业处理静态资源服务放一起对比的话那本身就已经输了
本身不需要异步处理的应用:比如自行化脚本,如果使用node的话效果上先不说好不好,光从写代码人文角度,一些异步回调的处理就给我们带来不必要的麻烦
说了这么多从现在开始让我们进行编码领域吧,毕竟实实在在的代码看着还是比较踏实
直接在官方网站下载 Node.js 源码或预编译安装包即可
控制台输入
$ node -v v12.16.3
出现此标示说明安装成功,12.16.3为当前最新LTS版本
工具三剑客 安装node后我们可以在安装几个软件,可以让我们使用node更加的便捷 npm nvm nrm这三个,主要是nvm和nrm因为npm一般安装node的时候已经自带了。
目前的版本里面都是自己携带了不用单独下载
nvm功能是切换node各个版本
下载方式很简单 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
不过nvm 的官方版本只支持 Linux 和 Macnvm官方文档。对Windows 用户不是很友好,针对windows可以使用nvm-windows其他设置官方里面写了很清楚。
nvm中常用的几种方式
nvm install ** 安装指定版本,如安装v12.0.0,既可nvm install v12.0.0
nvm uninstall ** 删除已安装的指定版本,如删除nvm uninstall v12.0.0
nvm use ** 切换使用指定的版本
nvm ls ** 列出所有安装的版本
nrm作用是切换npm源的,默认的源是npm官方源https://registry.npmjs.org/
安装直接
npm install -g nrm
执行nrm ls就可以看到你所指定的所有源
npm -------- https://registry.npmjs.org/ yarn ------- https://registry.yarnpkg.com/ cnpm ------- http://r.cnpmjs.org/ taobao ----- https://registry.npm.taobao.org/ nj --------- https://registry.nodejitsu.com/ npmMirror -- https://skimdb.npmjs.com/registry/ edunpm ----- http://registry.enpmjs.org/
如果想添加一个源的话直接执行
nrm add <registry> <url>
如果采用官方的源下载的时候可能会很慢,推荐大家安装淘宝的国内源https://registry.npm.taobao.org
nrm use taobao
更多细节可在nrm官方文档
最后在控制台输入node命令进行操作,就可以开始node开发之旅了
fengshi : ~ » node > 1+1 2
参考: https://nodejs.org/en/docs https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c
更多Node.js学习 交流关注微信公众号【一起学Node】,这里聚集Node专属爱好者使用者,一起进步成长
1. 定义
我们学习掌握一门新技术时候,第一步应当从它的官方文档开始认知,打开Node.js官方文档可以看到比较显眼的一句话是。
Node.js是建立在Chrome V8 上面的一个JavaScript运行环境
通俗点解释: js属于一种脚本性语言,然而脚本语言运行需要一个解析器来解析,对于我们原来写的js代码大部分都是运行在网页上,所以浏览器本身就担当了解析器的角色。而现在对于独立运行在服务器的js代码,node就属于那个解析器。
2. 发展史
node的诞生到目前也走过了10多年,一路走来辉煌过、质疑过、突围过、到目前,可谓天生我材必有用,千金散尽还复来。
所以笔者自己做了一个时间轴图来和大家一起见证下node在历史洪流中比较重要的时刻。
3. 特性
我们使用node可能听到最多的几个特性就是
3.1 单线程
Node JS的应用程序,是使用单线程以及事件循环体系结构组合,来处理客户端请求的,但实际上我们要明白不要误解的一点它只是主事件循环是单线程的, 其他的比如I / O处理相关的操作是有单独的线程去处理,因为Node JS中很多的I / O API在设计上本就是异步/非阻塞的,为了就是更方便适应主事件循环。
为此笔者也做了两个小图给大家描述下Node与传统服务器端环境之间的区别,可以看到不一样的点。
图1:
图二:
图1中
图2中
当然关于单线程多线程的问题知识点是有很多内容扩展的,大家可以关注后续章节为大家分享。
3.2 非阻塞I/O
说到非阻塞我们可能想到的就是和阻塞概念放在一起讨论
阻塞
阻塞的定义是指在 Node.js 程序中,其它 JavaScript 语句的执行,必须等待一个非 JavaScript 操作完成。这是因为当阻塞发生时,事件循环无法继续运行 JavaScript。 阻塞执行的方法都为同步执行执行,例如我们常见的文件读取案例就是典型的同步读取操作。
非阻塞
前面提到当阻塞发生时,事件循环无法继续运行 JavaScript。在非阻塞时当任何请求发送到服务器时,它不会将发送过来请求排队缓存。接受请求后并开始执行(如果它阻塞了操作),然后将其发送到对应的工作线程区域进行处理,并在代码执行完成后立即为该线程注册一个回调,然后触发相同的回调并进入事件队列,之后再次由事件循环处理响应发送到相应的客户端,在这里它几乎不会阻塞。
有朋友刚开始可能会认为异步和非阻塞差不多(我当时也是这么认为的),这种想法是错误的。
3.3 Event Loop
前两个是比较好容易理解, Event Loop这个特性很少有人说可以完完全全搞明白它到底是怎么运转的,更多的是大家通过一些优秀文章和讲解以及一些经验来理解,Event Loop也是贯穿这node的核心,熟悉理解对于node学生有大有帮助,在描述之前先和大家分享一点很多人对此的一些误解点。
误解点:有一个主线程在运行用户的js代码,另一个线程运行事件循环。每次异步操作发生时,主线程将工作移交给事件循环线程,一旦完成,事件循环线程将等待主线程以执行回调
实现情况:只有一个线程执行js代码,就是事件循环运行的线程,回调的执行是由事件循环完成的
误解点:异步操作(如处理文件系统、执行出站HTTP请求或与数据库通信)都是加载到libuv提供的线程池中进行执行处理
实际情况: Libuv在默认情况下创建一个线程池,其中有四个线程可以将异步工作转移到其中,然而如今的操作系统已经为许多I/O任务都提供了异步接口,在一定情况下,libuv将使用这些异步接口进行调用,避免使用线程池,只有在没有其他方法的情况下,线程池才会用于异步I/O
误解点:事件循环连续地遍历异步任务进行先进先出,并在任务完成时执行回调
现实情况:虽然涉及到类似队列的结构,但事件循环不会遍历并处理堆栈,作为事件循环是一组以循环方式处理特定任务的阶段
这几个是很多同学比较容易误区的几个点, 看到官方的一些描述是:
事件循环是 Node.js 处理非阻塞 I/O 操作的机制——尽管 JavaScript 是单线程处理的——当有可能的时候,它们会把操作转移到系统内核中去。
看了这些话可能不会所动,说的还是太官方了语言描述太简单了,就像我们的新闻描述一样字越少说明事越不简单,先不要急,再来看看对于事件循环机制的整个周期阶段说明,官方给出了一张图
从上图中大致可看出 事件循环的流程和大概:
数据输入–>轮询阶段(poll)–>检查阶段(check)–>关闭事件回调阶段(close callback)–>定时器检测阶段(timer)–>I/O 待定回调阶段(pending callbacks)–>闲置阶段(idle, prepare)–>轮询阶段(反复循环)
关于此知识点更详细的内容可查看官方文档
大家想深入了解的可以关注后续文章,在核心篇里会讲解扩展更多node相关知识点和实践
在看到两个比较好的动画图解释浏览器和node的事件循环的流程对比
浏览器的: (来源:Fundebug)
node的: (来源:Fundebug)
4. Node 应用与劣势
知道了它的诞生、特性、原理,下面我们来看看它的一些应用和不足,毕竟技术只有落地才是真理,不然说的再多都是白搭
4.1 应用领域
还有很多就不例举了,这些领域不是说是node专属的只是相对于其他从各方面考虑要适合一些
4.2 应用者
阿里:光一个egg.js就是最好的说明了
腾讯:微信小程序,云服务部分功能
网易:pomelo框架
Uber:每天使用Node处理20亿个远程过程调用(Remote Procedure Call,RPC)
PayPal:根据Node.js at PayPal,使用Node.js之后,应用开发速度提高了2倍;代码量减少了33%;文件数目减少了40%,并且,每秒处理的请求数增加了2倍,接口的请求时间减少了35%
像微软谷歌这些公司多年前就加入基金会了
因为这些头部公司的接入使用说明node的发展还是很成功的,但技术只有通过多个方面综合考虑如人力成本 学习成本等才能定下来,node发展迅速与采用js语言为基础学习成本低使用人数多,并和强大的npm社区密不可分,但这些不能掩盖它的一些缺点导致npm包的质量参差不齐。
只有正面node的一些缺点才可以更理性的看待它,就像TJ在决定离开node的时候说的,如果是web开发他还是会采用node,只不过他要开始转向分布式系统的开发了,所以不适合了。
4.3 劣势
计算密集型应用 如果非要把Javascript和C去拼计算性能,结果可想而知。
内存控制 把js和java比较复杂数据类型定义的话,也是不明智的。因为js的面向对象是基于JSON的,而java是直接使用内存结构。所以,通过JSON序列化和反序列的过程控制内存,js在开始就已经败了。
静态服务器,I/O密集应用固然是node的优势,但是你非要把它和Nginx这种专业处理静态资源服务放一起对比的话那本身就已经输了
本身不需要异步处理的应用:比如自行化脚本,如果使用node的话效果上先不说好不好,光从写代码人文角度,一些异步回调的处理就给我们带来不必要的麻烦
5. 环境安装
说了这么多从现在开始让我们进行编码领域吧,毕竟实实在在的代码看着还是比较踏实
5.1 工具包搭建
直接在官方网站下载 Node.js 源码或预编译安装包即可
控制台输入
出现此标示说明安装成功,12.16.3为当前最新LTS版本
工具三剑客 安装node后我们可以在安装几个软件,可以让我们使用node更加的便捷 npm nvm nrm这三个,主要是nvm和nrm因为npm一般安装node的时候已经自带了。
5.1.1 npm
目前的版本里面都是自己携带了不用单独下载
5.1.2 nvm
nvm功能是切换node各个版本
不过nvm 的官方版本只支持 Linux 和 Macnvm官方文档。对Windows 用户不是很友好,针对windows可以使用nvm-windows其他设置官方里面写了很清楚。
nvm中常用的几种方式
nvm install ** 安装指定版本,如安装v12.0.0,既可nvm install v12.0.0
nvm uninstall ** 删除已安装的指定版本,如删除nvm uninstall v12.0.0
nvm use ** 切换使用指定的版本
nvm ls ** 列出所有安装的版本
5.1.3 nrm
nrm作用是切换npm源的,默认的源是npm官方源https://registry.npmjs.org/
安装直接
执行nrm ls就可以看到你所指定的所有源
如果想添加一个源的话直接执行
如果采用官方的源下载的时候可能会很慢,推荐大家安装淘宝的国内源https://registry.npm.taobao.org
更多细节可在nrm官方文档
最后在控制台输入node命令进行操作,就可以开始node开发之旅了
参考: https://nodejs.org/en/docs https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c
更多Node.js学习 交流关注微信公众号【一起学Node】,这里聚集Node专属爱好者使用者,一起进步成长