Node 优势

Node在2009年被创造出来,最初的目的是作为一个轻量级的WEB服务器框架 WEB服务器很明显的特点是事件驱动以及非阻塞的IO处理,因此JavaScript作为了Node的实现语言

Node的特点

  1. 异步IO Node的最大特点是它的异步IO,相对其他语言,以python,Java以及C++为例,它们在处理文件读写时的操作如下:

  2. python

f = open("sxl.txt")
lines = f.read()
print lines
f.close()
  • Java

InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;

while ((lineTxt = bufferedReader.readLine()) != null){
  list.add(lineTxt);
}
bufferedReader.close();
read.close();
  • C++

char buffer[256];
ifstream in("test.txt");
if (! in.is_open()){
  cout << "Error opening file"; exit (1); 
}
while (!in.eof()){
  in.getline (buffer,100);
  cout << buffer << endl;
}

毫无疑问,在读写文件时,上述语言都是通过阻塞式的操作来处理,在读写完成之前,是会阻塞之后的操作,直到完成后才会继续执行 我们再来看一下Node的读写文件

  • Node

fs.readFile('input.txt', function (err, data) {
  if (err) {
      return console.error(err);
  }
  console.log("读取完成: " + data.toString());
});
console.log("发起读取文件");

Node提供了两种读取文件的模式,一种是上述异步的模式,一种是同步的模式。同步的模式类似其他的语言是会阻塞掉后面的操作,而上述异步的操作是会异步执行,当执行到读写文件的操作时,Node可以继续执行之后的代码,在读写文件完成的时候,将返回的结果传入第二个参数传入的回调函数之中,这样就实现了Node的异步IO

  1. 事件和回调函数

在前端的代码中,事件和回调函数的出现非常频繁,以绑定一个点击事件为例:

document.querySelect('body').addEventListener('click', () => {console.log('clicked')})

因为此类接口非常契合Node异步IO的思想,Node依旧保留了这一类接口。像之前Node读取文件的时的fs.readFile,在读取完成时触发完成事件,将与之相关的参数传入回调函数之中完成操作。 使用异步思想来编程时,需要对业务进行划分,将不同类的业务划分到不同的“回调函数”之中,由于异步的操作,对流程的控制以及对事件之间的协作可能会造成一些障碍

  1. 进程与线程

首先回顾下操作系统进程与线程的概念

  • 进程

    拥有独立的内存空间和端口,通过进程间通信来完成进程之间的协作

  • 线程

    任务执行的基本单元,在进程容器中执行,线程之间共享进程的资源比如内存,使用信号量和互斥锁来进行线程之间的协作

Node是单进程多线程的,在V8工作和文件读写的时候都会启动多个线程来进行工作,在Node v10.5.0之后,可以使用worker_thread模块来进行线程级的开发。Node的线程与操作系统中的线程不同的是,线程间无法共享内存,线程之间传递数据只能使用进程通信的机制(postmessage() / on('message', callback))来传递

虽然Node是单进程的,但是我们可以通过child_process来创建一个子进程,使用Master-Worker的模式,通过父进程和多个子进程的模式来将计算拆分到子进程中计算,通过进程之间的通信来传输数据,这样可以利用起多核CPU,带来更强的健壮性

Node的应用场景

  1. IO密集型

Node面向网络擅长IO操作,在IO的密集处理上是首屈一指的,Node无需为单独一个请求开启线程,而是使用异步IO和事件循环的能力,能更少的占用资源

  1. CPU密集型

在执行效率上,V8的效率是非常高的,在处理CPU密集型的业务时,有以下几个方式来充分利用CPU

  • 编写C/C++扩展,将一些V8不用做到极致的计算使用C++来计算

  • 使用子进程,将IO与计算分离,利用CPU核数

  • 使用worker_thread进行多线程的开发

最后更新于