gongmw / blog

从现象 看本质
117 stars 12 forks source link

Node.js前世今生 #17

Open gongmw opened 4 years ago

gongmw commented 4 years ago

1. 定义

我们学习掌握一门新技术时候,第一步应当从它的官方文档开始认知,打开Node.js官方文档可以看到比较显眼的一句话是。

在这里插入图片描述

Node.js是建立在Chrome V8 上面的一个JavaScript运行环境

通俗点解释: js属于一种脚本性语言,然而脚本语言运行需要一个解析器来解析,对于我们原来写的js代码大部分都是运行在网页上,所以浏览器本身就担当了解析器的角色。而现在对于独立运行在服务器的js代码,node就属于那个解析器。

V8属于Google Chrome 浏览器的一个高性能引擎,可以直接将JavaScript编译为本地机器代码,而其他的语言如PHP和Ruby,Java每次访问时都必须通过解释器运行。

2. 发展史

node的诞生到目前也走过了10多年,一路走来辉煌过、质疑过、突围过、到目前,可谓天生我材必有用,千金散尽还复来

所以笔者自己做了一个时间轴图来和大家一起见证下node在历史洪流中比较重要的时刻。

在这里插入图片描述

此外我还收集整理了两篇关于NodeJS创始人Ryan Dahl的访谈录,一篇是10年前的 Ryan Dahl的访谈和一篇近期对Ryan Dahl的访谈, 虽然内容不是很多关于NodeJs技术层面的问题和教程,但记者对Ryan Dahl提的一些有趣的问题,和Ryan Dahl的回答会让你感觉很有趣也会让你对Node有一些不一样的见解,如果大家对访谈录感兴趣的可以关注我的微信公众号一起学Node中查看,可以带你了解NodeJs的前世今生。

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。 阻塞执行的方法都为同步执行执行,例如我们常见的文件读取案例就是典型的同步读取操作。

const fs = require('fs');
const data = fs.readFileSync('/file.txt'); 

非阻塞

前面提到当阻塞发生时,事件循环无法继续运行 JavaScript。在非阻塞时当任何请求发送到服务器时,它不会将发送过来请求排队缓存。接受请求后并开始执行(如果它阻塞了操作),然后将其发送到对应的工作线程区域进行处理,并在代码执行完成后立即为该线程注册一个回调,然后触发相同的回调并进入事件队列,之后再次由事件循环处理响应发送到相应的客户端,在这里它几乎不会阻塞。

有朋友刚开始可能会认为异步和非阻塞差不多(我当时也是这么认为的),这种想法是错误的。

异步和非阻塞虽然都达到了我们并行 I/O 的目的。但是从计算机内核 I/O 而言,异步 / 同步和阻塞 / 非阻塞实际上是两回事

3.3 Event Loop

前两个是比较好容易理解, Event Loop这个特性很少有人说可以完完全全搞明白它到底是怎么运转的,更多的是大家通过一些优秀文章和讲解以及一些经验来理解,Event Loop也是贯穿这node的核心,熟悉理解对于node学生有大有帮助,在描述之前先和大家分享一点很多人对此的一些误解点。

  1. 事件循环和用户代码运行在不同的线程中

误解点:有一个主线程在运行用户的js代码,另一个线程运行事件循环。每次异步操作发生时,主线程将工作移交给事件循环线程,一旦完成,事件循环线程将等待主线程以执行回调

实现情况:只有一个线程执行js代码,就是事件循环运行的线程,回调的执行是由事件循环完成的

  1. 所有的异步操作都由线程池处理

误解点:异步操作(如处理文件系统、执行出站HTTP请求或与数据库通信)都是加载到libuv提供的线程池中进行执行处理

实际情况: Libuv在默认情况下创建一个线程池,其中有四个线程可以将异步工作转移到其中,然而如今的操作系统已经为许多I/O任务都提供了异步接口,在一定情况下,libuv将使用这些异步接口进行调用,避免使用线程池,只有在没有其他方法的情况下,线程池才会用于异步I/O

libuv 是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的 API

  1. 事件循环类似于堆栈或队列

误解点:事件循环连续地遍历异步任务进行先进先出,并在任务完成时执行回调

现实情况:虽然涉及到类似队列的结构,但事件循环不会遍历并处理堆栈,作为事件循环是一组以循环方式处理特定任务的阶段

这几个是很多同学比较容易误区的几个点, 看到官方的一些描述是:

事件循环是 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 应用者

因为这些头部公司的接入使用说明node的发展还是很成功的,但技术只有通过多个方面综合考虑如人力成本 学习成本等才能定下来,node发展迅速与采用js语言为基础学习成本低使用​人数多,并和强大的npm社区密不可分,但这些不能掩盖它的一些缺点导致npm包的质量参差不齐。

只有正面node的一些缺点才可以更理性的看待它,就像TJ在决定离开node的时候说的,如果是web开发他还是会采用node,只不过他要开始转向分布式系统的开发了,所以不适合了。

4.3 劣势

5. 环境安装

说了这么多从现在开始让我们进行编码领域吧,毕竟实实在在的代码看着还是比较踏实

5.1 工具包搭建

直接在官方网站下载 Node.js 源码或预编译安装包即可

控制台输入

   $ node -v
   v12.16.3 

出现此标示说明安装成功,12.16.3为当前最新LTS版本

工具三剑客 安装node后我们可以在安装几个软件,可以让我们使用node更加的便捷 npm nvm nrm这三个,主要是nvm和nrm因为npm一般安装node的时候已经自带了。

5.1.1 npm

目前的版本里面都是自己携带了不用单独下载

5.1.2 nvm

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其他设置官方里面写了很清楚。

更多细节可在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专属爱好者使用者,一起进步成长

QQ20200724-155125@2x