Node.js整理

165 阅读5分钟

1. 说说你对Node.js 的理解?优缺点?应用场景?

Node.js 是一个开源与跨平台的 JavaScript 运行时环境

  在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能

  可以理解为 Node.js 就是一个服务器端的、非阻塞式I/O的、事件驱动的JavaScript运行环境

  非阻塞异步

  Nodejs采用了非阻塞型I/O机制,在做I/O操作的时候不会造成任何的阻塞,当完成之后,以时间的形式通知执行操作

  例如在执行了访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率

  事件驱动

  事件驱动就是当进来一个新的请求的时,请求将会被压入一个事件队列中,然后通过一个循环来检测队列中的事件状态变化,如果检测到有状态变化的事件,那么就执行该事件对应的处理代码,一般都是回调函数

比如读取一个文件,文件读取完毕后,就会触发对应的状态,然后通过对应的回调函数来进行处理

图片1.png Node.js不是一种独立的语言,是一种新的方式,Node.js使用JavaScript进行编程,运行在JavaScript(V8)引擎上。与PHP、JSP等相比,Node.js跳过了Apache、Nginx、IIS等HTTP服务器,它不用建设在任何服务器软件之上,处理能力优越。Node使得编写可扩展性高的服务器变得既容易又安全。

提高服务器性能的技巧有多种多样。Node是一种既能提高性能,又能减低开发复杂度的架构。这是一个非常重要的特性。

node的特点:

  1. 它是一个Javascript运行环境

  2. 依赖于Chrome V8引擎进行代码解释

  3. 事件驱动

  4. 非阻塞I/O

  5. 轻量、可伸缩,适于实时数据交互应用

  6. 单进程,单线程

node的优缺点

优点:

  1. 高并发(最重要的优点)

  2. 适合I/O密集型应用

缺点:

  1. 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;

解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;

  1. 只支持单核CPU,不能充分利用CPU

  2. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃

缺点的原因及解决方案:

(1)Nginx反向代理,负载均衡,开多个进程,绑定多个端口;

(2)开多个进程监听同一个端口,使用cluster模块;

  1. 开源组件库质量参差不齐,更新快,向下不兼容

  2. Debug不方便,错误没有stack trace

 

具体场景可以表现为如下:

第一大类:用户表单收集系统、后台管理系统、实时交互系统、考试系统、联网软件、高并发量的web应用程序

第二大类:基于web、canvas等多人联网游戏

第三大类:基于web的多人实时聊天客户端、聊天室、图文直播

第四大类:单页面浏览器应用程序

第五大类:操作数据库、为前端和移动端提供基于json的API

2. Nodejs 和 JavaScript 有什么不同

(1) JavaScript是一种脚本语言,而Node.js是一个让 JavaScript运行在服务端的开发平台。

(2) 在ECMAScript部分node和JS其实是一样的,比如与数据类型的定义、语法结构,内置对象,都是ECMAScript。NodeJS是以ECMASCRIPT为基础,然后在这个基础上扩展出来的一些操作其他东西(即操作非浏览器)的一些方法,比如操作OS操作系统、file文件系统、net网络、database数据库等。也就是说nodejs和JS在底层都是一样的,都是ECMAScript,但是扩展出来的功能却是不一样的。一个是偏向于前端浏览器,一个是偏向于后端。

(3) 顶层对象不同 。js中的顶层对象是window对象,但是在node中没有什么window对象,node中的顶层对象是global对象。这就是二者的差异性。在window对象中,定义一个全局变量是可以通过Window来访问的,但是在node中是不能通过global对象来访问的

3. Node.js 是怎么工作的

Node.js 中有一个重要的机制叫做事件循环,能够让单线程的 JavaScript 执行非阻塞的 I/O 操作。事件循环从代码中获取任务并执行。如果任务是异步的或者是一个 I/O 操作,则事件循环将它交给系统内核执行(例如建立新的连接)或线程池(如与文件系统相关的操作)。然后事件循环将会获取下一个任务去执行。

由于大多数现代的内核是支持多线程的,所以可以在后台同时执行多个操作。当其中的某一个操作完成的时候(这是一个事件),内核将通知 Node.js ,Node.js 会把回调函数添加到轮询队列中,然后被执行。

为适应单线程事件循环,Node.js 使用 libuv 库,而 libuv 又使用固定大小的线程池来并行处理一些非阻塞异步 I/O 操作。主线程调用函数将任务发送到共享任务队列,然后线程池中的线程将执行这些任务。