225 lines
12 KiB
JavaScript
225 lines
12 KiB
JavaScript
|
## 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)
|