什么是Node
首先JavaScript是一门编程语言,就像Java、Python、C#、GO一样,在Node出来之前,JavaScript主要运行于浏览器中,用来控制页面的展示逻辑,以及交互操作等。JavaScript之所以能够在浏览器中执行,是因为浏览器中都有JavaScript的解析引擎,不同的浏览器的解析引擎是不同的。
当然除了这些解析引擎外还有其他的解析引擎:比如说quickjs等。
那么JavaScript是如何和浏览器进行交互的,我们都知道,浏览器是用C++进行编写的,他会去解析Html,Css等进行渲染,因为这些都是规则(也就是约定,或者是接口)。对于JavaScript也一样,浏览器也会提供一些接口,然后,解析器将我们的JavaScript规则转换成调用浏览器接口的东西,这样就促成了JavaScript和浏览器的交互。
而Node就是建立的在V8解析引擎上面,将调用系统的功能进行了封装,而中间
Node的特点
对NodeJs其特点有以下几个方面:
- Node是一个Javascript运行环境,依赖于Chrome V8引擎进行代码解释
- 单进程,单线程(这里指主线程)
- 非阻塞I/O
- 异步事件驱动
- 性能出众
接下来就意义介绍其上述的几个特点:
Node是一个JavaScript运行环境,依赖于Chrome V8引擎进行代码解释
简单来说,CPU并不认识我们的JavaScript代码,而不同的CPU只认识自己对应的指令集,JavaScript引擎将js代码编译成CPU认识的指令集,当然除了编译之外还要负责执行以及内存的管理。另外JavaScript是解释形语言,由引擎直接读取源码,一边编译一边执行,这样效率相对较低,而编译形语言(如c++)是把源码直接编译成可直接执行的代码执行效率更高。而V8引擎则是一种高效的JavaScript的引擎
V8引擎是一个JavaScript引擎实现,最初由一些语言方面专家设计,后被谷歌收购,随后谷歌对其进行了开源。V8使用C++开发,,在运行JavaScript之前,相比其它的JavaScript的引擎转换成字节码或解释执行,V8将其编译成原生机器码(IA-32, x86-64, ARM, or MIPS CPUs),并且使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript程序在V8引擎下的运行速度媲美二进制程序。V8支持众多操作系统,如windows、linux、android等,也支持其他硬件架构,如IA32,X64,ARM等,具有很好的可移植和跨平台特性。
单进程,单线程(这里指主线程)
对于NodeJS来说,其中的JavaScript的执行是单线程的(这里的单线程是指主线程是单线程)。所有的任务都放在同一个任务执行队列里面去(当然任务会被分为基本任务,宏任务和微任务。只是不同的任务类型在任务队列里里面执行的方式不一样而已)。
非阻塞I/O
- I/O(输入/输出):是在主存和外部设备(例如磁盘,终端和网络。这里的外部设备又被称之为I/O设备)之间复制数据的过程。输入操作是从外部设备复制数据到主存,输出操作则是从主存复制 数据到外部设备。
- 阻塞:线程发起一个调用时, 在调用返回之前, 线程会被阻塞, 在这个状态下会交出当前CPU的使用权而暂停.也就是调用方会等待调用结果, 调用阻塞了调用方的线程, 线程不在运行处理中。
- 非阻塞:线程发起一个调用时, 调用会立即返回, 避免线程被阻塞。但是, 返回的结果只是被调用方当前状态的值, 实际使用时, 调用方需要轮询, 直到返回结果符合预期(直到数据准备好)。
一个完整的IO请求的主要包括有两个阶段:
1、查看数据是否就绪;
2、进行数据拷贝(内核将数据拷贝到用户线程)。
阻塞(blocking IO)和非阻塞(non-blocking IO)的区别就在于第一个阶段,如果数据没有就绪,再查看数据是否就绪的过程中是一直等待,还是直接返回一个标志信息。
非阻塞,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高。
异步事件驱动
这中间其实有三个概念,异步、事件和事件驱动。我们挨个介绍。
- 事件:就是两个物体之间产生了交互行为,就可以成为一个事件。比如说我们点击一个按钮,就称为次事件。
- 事件驱动:就是两个之间产生了交互行为,驱使两个物体的一方,做出了相应的行为或动作。比如说我们单击一个按钮,弹出了一个弹框,那么这个弹框的这个行为,就是我们点击的驱动。
- 异步:异步和同步是相对的,同步就是一件事一件事的执行。只有前一个任务执行完毕,才能执行后一个任务。而异步,是一个任务一个人的调用,而不用等待上一个任务执行完毕,直接开始第二次任务,当上一个任务执行完成后,会通知做后续的操作。我们打个比方,就是我们点击一个按钮,去请求数据,同时改变一下按钮的状态,如果我们等待请求结束后,再去修改按钮状态,这样给人的感受就会特别的奇怪。
在Node底层采用了Libuv这个库,Libuv是一个跨平台的的基于事件驱动的异步io库。但是他提供的功能不仅仅是io,包括进程、线程、信号、定时器、进程间通信等。
性能出众
底层选择用c++和v8来实现的,上面第一点讲到过,nodejs的事件驱动机制,这意味着面对大规模的http请求,nodejs是凭借事件驱动来完成的,性能部分是不用担心的,并且很出色。
Node的优势
-
1、Nodejs语法完全是js语法,只要你懂js基础就可以学会Nodejs后端开发
Node打破了过去JavaScript只能在浏览器中运行的局面。前后端编程环境统一,可以大大降低开发成本。
-
NodeJs超强的高并发能力
NodeJs的首要目标是提供一种简单的、用于创建高性能服务器及可在该服务器中运行的各种应用程序的开发工具。
首先让我们来看一下现在的服务器端语言中存在着什么问题。在Java、PHP或者.NET等服务器语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。要让web应用程序支持更多的用户,就需要增加服务器的数量,而web应用程序的硬件成本当然就上升了。
NodeJs不为每个客户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用Node.js,一个8GB内存的服务器,可以同时处理超过4万用户的连接。
-
实现高性能服务器
严格地说,Node.js是一个用于开发各种web服务器的开发工具。在Node.js服务器中,运行的是高性能V8 JavaScript脚本语言,该语言是一种可以运行在服务器端的脚本语言。
那么,什么是V8 JavaScript脚本语言呢?该语言是一种被V8 JavaScript引擎所解析并执行的脚本语言。V8 JavaScript引擎是由Google公司使用C++语言开发的一种高性能JavaScript引擎,该引擎并不局限于在浏览器中运行。Node.js将其转用在了服务器中,并且为其提供了许多附加的具有各种不同用途的API。例如,在一个服务器中,经常需要处理各种二进制数据。在JavaScript脚本语言中,只具有非常有限的对二进制数据的处理能力,而Node.js所提供的Buffer类则提供了丰富的对二进制数据的处理能力。
另外,在V8 JavaScript引擎内部使用一种全新的编译技术。这意味着开发者编写的高端的 JavaScript 脚本代码与开发者编写的低端的C语言具有非常相近的执行效率,这也是Node.js服务器可以提供的一个重要特性。
-
开发周期短、开发成本低、学习成本低
Node.js自身哲学,是话最小的硬件成本,追求更高的并发,更高的处理性能。
Node有哪些缺点
- 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;
解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;
-
只支持单核CPU,不能充分利用CPU
-
可靠性低,一旦代码某个环节崩溃,整个系统都崩溃
原因:单进程,单线程
解决方案:(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;
(2)开多个进程监听同一个端口,使用cluster模块;
-
开源组件库质量参差不齐,更新快,向下不兼容
-
Debug不方便,错误没有stack trace
Node适合用来干什么
前端工具的脚手架、辅助工具类
发展到api中间层、代理层
以及专业的后端开发