## todo

-   rpc 和 Node.js 的关系

-   [《吊打面试官》系列 Node.js 全栈秒杀系统](https://mp.weixin.qq.com/s/uWeAsJ-P253je15A49uKIQ)

## 前言

Node 的重要性已经不言而喻，很多互联网公司都已经有大量的高性能系统运行在 Node 之上。Node 凭借其单线程、异步等举措实现了极高的性能基准。此外，目前最为流行的 Web 开发模式是前后端分离的形式，即前端开发者与后端开发者在自己喜欢的 IDE 上独立进行开发，然后通过 HTTP 或是 RPC 等方式实现数据与流程的交互。这种开发模式在 Node 的强大功能的引领下变得越来越高效，也越来越受到各个互联网公司的青睐。

### 前端同学为什么要学习后台开发

-   了解前后端交互流程。

-   能够和后台开发的程序员更佳紧密地结合、更顺畅地沟通。

-   当网站的业务逻辑需要前置时，前端人员需要学习一些后台开发的技术，以完成相应的任务。

-   拓宽知识视野和技术栈，能够站在全局的角度审视整个项目。

### 前端同学为什么要学 Node.js

1、Node.js 使用 JavaScript 语言开发服务器端应用，**便于前端同学上手**（一些公司甚至要求前端工程师掌握 Node.js 开发）。

2、实现了前后端的语法统一，**有利于和前端代码整合**，甚至共用部分代码。

比如说，针对接口返回的各种字段，前后端都必须要做校验。此时，如果用 Node.js 来做后台开发的话，前后端可以共用校验的代码。

3、Node.js 性能高、生态系统活跃，提供了大量的开源库。

4、Jeff Atwood 在 2007 年提出了著名的 Atwood 定律：**任何能够用 JavaScript 实现的应用系统，最终都必将用 JavaScript 实现**。如果你不知道 Jeff Atwood 是谁（他是 Stack Overflow 网站的创始人），这不重要，重要的是这条定律。

### 后端同学为什么要学 Node.js

因为前端同学在学 Node.js。

## Node.js 的介绍

### 什么是 Node.js

[Node.js](https://nodejs.org/zh-cn/) 是一个基于 **Chrome V8** 引擎的 JavaScript 运行环境。Node.js 使用了一个**事件驱动**、**非阻塞式 I/O**的模型（ Node.js 的特性），使其轻量级又高效。Node.js 的包管理工具 npm 是全球最大的开源库生态系统。

![](http://img.smyhvae.com/20180301_1540.png)

如上图所示：

-   Node.js 不是一门语言，也不是 JavaScript 的框架，也不是像 **Node.js 是 JavaScript 在服务器端的运行环境（平台）**。

-   Node.js 内部采用 Google Chrome 的 V8 引擎，作为 JavaScript 语言解释器；同时结合自行开发的 libuv 库，扩展了 JS 在后端的能力，使得 JS 既可以在前端进行 DOM 操作（浏览器端），又可以在后端调用操作系统资源（I/O 操作、文件读写、数据库操作等），是目前最简单的全栈式语言。

备注 1：[V8 引擎](https://v8.dev/) 本身是用 C++ 写的。 [libuv](https://zh.wikipedia.org/wiki/Libuv) 这个库本身也是用 C/C++ 写的。

备注 2：限制语言能力的不是语言本身，而是语言的生态。

### Node.js 的组成

我们知道，JavaScript 的组成分为三个部分：

-   ECMAScript

-   DOM

-   BOM

ECMAScript 是 JS 的语法；DOM 和 BOM 浏览器运行环境为 JS 提供的 API。

而 Node.js 的组成分为：

-   **ECMAScript**。ECMAScript 的所有语法在 Node 环境中都可以使用。

-   **Node 环境**提供的一些**附加 API**(包括文件、网络、路径等等 API)。

如下图所示：

![](http://img.smyhvae.com/20200409_1545.png)

### 补充

JS 语言非常灵活，使得它在严谨性方面不如 Java 等传统的静态语言。JS 是一门动态语言，而且融合了面向对象和函数式编程这两种编程范式。

随着 ES6、ES7 等 JS 语法规范的出现，以及浏览器对这些规范的支持，使得我们可以用更为现代化的 JS 语言特性，来编写现代化的应用。

## Node 的发展历史

-   2008 年左右，随着 Ajax 的逐渐普及，Web 开发逐渐走向复杂化，系统化；

-   Node.js 诞生于 2009 年，由 Joyent 的员工 Ryan Dahl 开发而成。2009 年 5 月，Ryan Dahl 在 GitHub 中开源了 Node 的最初版本，同年 11 月，在 JSConf 大会上展示了 Node 项目；

-   2010 年 1 月，NPM 包管理工具诞生，使得程序员能够更方便地发布和分享 Node.js 的第三方库。

-   Node.js 最初只支持 Linux 和 Mac OS 操作系统。2011 年 7 月，微软参与合作，Node.js 终于支持了 Windows 平台。PS：不过，node 的生产环境基本是在 Linux 下。

-   目前官网最新版本已经更新到 14.x.x 版本，最新稳定的是 12.18.0。

据 Node.js 创始人 Ryan Dahl 回忆，他最初希望采用 Ruby，但是 Ruby 的虚拟机效率不行。

注意：是 Node 选择了 JavaScript，不是 JavaScript 发展出来了一个 Node。

## Node.js 的应用

Node.js 拥有强大的开发者社区，现在已经发展出比较成熟的技术体系，以及庞大的生态。它被广泛地应用在 Web 服务、开发工作流、客户端应用等诸多领域。其中，在 Web 服务领域，业界对 Node.js 的接受程度最高。

### Node.js 的用途

**1、中间层**。

前端访问中间层的接口，中间层再访问后台的 Java/C++ 服务。这类服务的特点是不需要太强的服务器运算能力，但对程序的灵活性有较高的要求。

这样做的好处是：安全性（不会把主服务器暴露在外面）、提高性能（做缓存等）、降低主服务器的复杂度。

当然，有时候做 Node.js 开发，是因为：后台人力不够，所以把后台开发的一部分工作量，转移给前端同学。

**2、做小型服务、小型网站的后端**（比如后台管理系统）。

现在很多公司的后台管理系统，都是用 Node.js来开发接口，直接操作 DB。

不过，短期来看，Node.js 很难像 Java/C++ 那样，成为后台的主力开发语言。这并非是因为 Node.js 的性能问题（实际上，Node.js 的性能还不错），主要是因为，Node.js 还比较年轻，框架的支持度不够，很难独立成为后台开发语言；但未来可期。

**3、做公司内部工具、项目构建工具**。



### Node.js 的主要应用领域

-   RESTFul API

-   实时通信：如消息推送等

-   高并发

-   I/O 阻塞

### 知名度较高的 Node.js 开源项目

![](http://img.smyhvae.com/20180301_2009.png)

-   express：Node.js 中著名的 web 服务器框架。

-   Koa：下一代的 Node.js 的 Web 框架。

-   mocha：功能强大的 node.js 测试框架。

-   PM2：node 本来是单进程的，PM2 可以实现和管理多进程。

-   jade：非常优秀的模板引擎，不仅限于 js 语言。

-   CoffeeScript：用简洁的方式展示 JavaScript 优秀的部分。

-   Atom：文本编辑器。

-   socket.io：实时通信框架。

## 前端同学会 Node.js 就真的全栈了吗？

一个人的精力是有限的，既擅长前端、又精通后端的人，毕竟是极少数。

林肯说过：“你可以在所有的时间欺骗一部分人，也可以在一段时间欺骗所有的人，但你不可能在所有的时间欺骗所有的人”。

同样的，我也说过：“你可以在这一段时间擅长前端技术，也可以在另一段时间擅长后台技术，但你不可能在**同一段时间**同时擅长前端和后台，更不可能在**所有的时间**同时擅长前端和后台。”

所谓的全栈，只是一个伪命题。个人不一定需要全栈，企业和项目也不强制要求全栈，分工协作，才最高效。

对于个人而言，虽然全栈很难，但是 Node.js 的出现，**让 JS 语言实现了前后端语法的统一，让 JS 语言的技术栈更佳全面**。

涉及到后台开发相关的技术，无论如何，也绕不开**框架设计、开发调试、数据库操作、高并发处理、大规模存储、性能优化、容灾方案、操作系统调度、甚至是 Linux 内核、驱动开发**等过硬的知识技能和经验积累。等你亲身经历过这些，才算明白：语言只是一种工具。

## V8 引擎

### 运行环境（平台）的含义

首先，JavaScript 语言通过 Node 在服务器上运行，在这个意义上，Node.js 的地位相当于 JavaScript 在服务器端的虚拟机，类似于 Java 语言中的 Java 虚拟机。

其次，Node 生态系统活跃，提供了大量的开源库，使得 JavaScript 语言能与操作系统进行交互，在这个层次上，Node 又是属于 JavaScript 的工具库。

**补充**：

与 PHP、JSP、Python、Perl、Ruby 的“既是语言，也是平台”不同，Node.js 的使用 JavaScript 进行编程，运行在 Chrome 的 V8 引擎上。

与 PHP、JSP 等相比（PHP、JSP、.net 都需要运行在服务器程序上，Apache、Nginx、Tomcat、IIS。
），Node.js 跳过了 Apache、Naginx、IIS 等 HTTP 服务器，它自己不用建设在任何服务器软件之上。Node.js 的许多设计理念与经典架构（LAMP = Linux + Apache + MySQL + PHP）有着很大的不同，可以提供强大的伸缩能力。Node.js 没有 web 容器。

### V8 和 Node

Chrome 浏览器成功的背后，离不开 JS 的 V8 引擎。作为虚拟机，V8 的性能表现优异，它的开发者是 Lars Bak。在 Lars 的工作履历里，绝大部分都是与虚拟机相关的工作。在开发 V8 之前，他曾经在 Sun 公司工作，担任 HotSpot 团队的技术领导，主要致力于开发高性能的 Java 虚拟机。在这之前，他也曾为 Self、Smalltalk 语言开发过高性能虚拟机。这些无与伦比的经历让 V8 一出世就超越了当时所有的 JS 虚拟机。

![](http://img.smyhvae.com/20200617_1120.png)

V8 的性能优势使得用 JavaScript 写高性能后台服务程序成为可能。在这样的契机下，Ryan Dahl 选择了 JavaScript，选择了 V8，在事件驱动、非阻塞 I/O 模型的设计下实现了 Node。

### V8 的内存限制

在一般的后端开发语言中，在基本的内存使用上没有什么限制，然而在 Node 中通过 JavaScript 使用内存时就会发现只能使用部分内存（64 位系统下约为 1.4GB，32 位系统下约为 0.7GB）。在这样的限制下，将会导致 Node 无法直接操作大内存对象。

造成这个问题的主要原因在于 Node 基于 V8 构建，所以在 Node 中使用的 JavaScript 对象基本上都是通过 V8 自己的方式来进行分配和管理的。V8 的这套内存管理机制在浏览器的应用场景下使用起来绰绰有余，足以胜任前端页面中的所有需求。但在 Node 中，这却限制了开发者随心所欲使用大内存的想法。

## Node.js 的特点

-   异步、非阻塞 IO 模型

-   事件循环

-   单线程

-   总结：轻量和高效

Node.js 的性能和效率非常高。

传统的 Java 语言是一个请求开启一个线程，当请求处理完毕后就关闭这个线程。而 Node.js 则完全没有采用这种模型，它本质上就是一个单线程。

你可能会疑问：一个线程如何服务于大量的请求、如何处理高并发的呢？这是因为，Node.js 采用的是异步的、非阻塞的模型。

这里所谓的“单线程”，指的是 Node 的主线程只有一个。为了确保主线程不被阻塞，主线程是用于接收客户端请求。但不会处理具体的任务。而 Node 的背后还有一个线程池，线程池会处理长时间运行的任务（比如 IO 操作、网络操作）。线程池里的任务是通过队列和事件循环的机制来执行。

## SSR 服务端渲染

提高搜索引擎抓取网页的

## 我的公众号

想学习**代码之外的技能**？不妨关注我的微信公众号：**千古壹号**（id：`qianguyihao`）。

扫一扫，你将发现另一个全新的世界，而这将是一场美丽的意外：

![](http://img.smyhvae.com/20200101.png)
