更新于 

第一章 Node简介

决定Web服务器性能的到底是什么?

大多数人不能设计一种更简单和更有效率的程序的主要原因是他们用到了阻塞I/O的库

Node的发明者 Ryan Dahl 认为高性能Web服务器需要考虑到两个要点:

  • 事件驱动
  • 非阻塞I/O

这也是 Ryan Dahl 选择 JavaScript 编写 Node 的原因,
因为 JavaScript 具有的优点和他对高性能Web服务器的要求都对上了,
JavaScript 在他眼中:

  • 一是 高性能(V8引擎)
  • 二是 符合事件驱动(浏览器中应用)
  • 三是 历史短

Node与开源精神

强制不共享任何资源

Node现在已经发展为一个 强制不共享任何资源 的单线程、单进程系统。
并且它自身也非常简单,通过通信协议来组织许多Node,
非常容易通过扩展来达成构建大型网络应用的目的。

对比Node与浏览器

浏览器的两个主要引擎
  • JavaScript引擎: V8
  • 布局引擎: WebKit

长久以来浏览器都是JavaScript运行的沙箱,
它的能力取决于浏览器中间层提供的支持有多少。

对比浏览器与Node

除了浏览器具有HTML、WebKit和显卡这些 UI相关技术 的支持外,
Node与浏览器结构十分相似,都是 基于事件驱动的异步架构

总之,Node不处理UI,但用与浏览器相同的机制和原理运行。

浏览器
通过事件驱动来服务 界面上的交互

Node
通过事件驱动来服务 I/O

Node的特点

异步I/O

经典异步调用——ajax请求
经典异步调用——ajax请求
Node中的异步读取文件操作
Node中的异步读取文件操作

Ryan Dahl 在底层构建了很多异步I/O的API,
因此我们可以从语言层面很自然的进行 并行I/O 操作

事件与回调函数

Node能够将事件点暴露给业务逻辑

事件编程

将前端浏览器中应用广泛且成熟的事件引入后端,配合异步I/O,将事件点暴露给业务逻辑

这也就是所谓的事件编程,优点是:

  • 轻量级
  • 松耦合
  • 只关注事务点

存在的问题是:

多个异步任务的场景下,事件与事件之间各自独立,如何协作是一个问题。

回调函数

回调函数是最好的接受异步调用返回数据的方式

异步编程思维要求熟悉:

  • 对业务的划分
  • 对事件的提炼

单线程

JavaScript与其余线程无法共享任何状态

单线程的弱点主要有:

  • 无法利用 多核CPU
  • 错误会 引起整个应用退出, 应用 健壮性
  • 大量计算占用CPU 导致无法继续调用异步I/O
child_process

Node使用child_process来解决单线程中大计算量的问题。

通过将计算分发到各个子进程,
再通过进程之间的事件消息来传递结果

跨平台

借助libuv组件,Node实现了跨平台的兼容

Node应用场景

I/O密集型

Node面向网络且擅长并行I/O,能够有效组织起更多的硬件资源

事件循环处理

Node利用事件循环处理密集I/O,
而不是启动每一个线程为每一个请求服务,资源占用极少

CPU密集型

Node的运行效率算得上高效吗?

答: Node当然足够高效,主要归功于V8的深度性能优化。

CPU密集型给Node带来的挑战是什么?

对于长时间的运算(如大循环)会导致CPU时间片长时间无法释放,
由于Node单线程的特点,后续I/O无法发起。

Node的对应策略
方法1:分解

适当调整和分解大型运算任务为多个小任务。

方法2:异步I/O

Node的异步I/O已经解决了单线程上CPU与I/O之间阻塞无法重叠利用的问题