Node.js

Node.js 知识量:9 - 37 - 115

9.1 多进程架构><

Web服务器的架构变迁- 9.1.1 -

Web服务器的架构变迁历史可以大致分为以下几个阶段:

  1. 单体服务器阶段:在这个阶段,Web服务器、数据库服务器和应用服务器都集成在一个物理机器上。这种架构简单,易于部署和管理,但扩展性较差。

  2. 物理分离阶段:随着访问量的增加,单体服务器难以满足性能和可扩展性的需求。因此,Web服务器、数据库服务器和应用服务器开始从物理上分离,成为独立的机器。这种架构提高了系统的可扩展性和可靠性。

  3. 应用服务器和数据库服务器的分离:随着业务复杂性的增加,应用服务器和数据库服务器之间的耦合度越来越高,性能瓶颈也日益凸显。因此,应用服务器和数据库服务器开始分离,以提高系统的性能和可维护性。

  4. 应用服务器集群的出现:随着访问量的继续增加,单台应用服务器已经无法满足需求。因此,应用服务器集群开始出现,通过多台服务器的协同工作来提高系统的可扩展性和可靠性。

  5. 分布式架构的出现:随着Web应用的复杂性和用户需求的增加,分布式架构开始成为主流。分布式架构将不同的组件分布在不同的地理位置和网络节点上,从而提高系统的可用性、可扩展性和容错性。

  6. 容器化和云化:随着容器技术的兴起和云服务的普及,Web服务器开始向容器化和云化转变。容器化技术使得应用可以打包在独立的容器中,实现快速部署和管理。云化则将计算资源抽象化为服务,按需使用和管理。

多进程架构- 9.1.2 -

Node.js可以通过多进程架构来提高应用程序的可扩展性和性能。多进程架构通常包括以下几种方式:

  • 进程间通信:Node.js提供了child_process模块,通过fork()函数创建子进程,实现进程间的通信。子进程可以与父进程进行通信,将结果返回给父进程。进程间通信可以提高应用程序的性能和可扩展性。

  • 事件驱动架构:Node.js是单线程的,但通过事件驱动的方式处理异步操作。在多进程架构中,每个进程都可以处理自己的事件循环,从而实现并发处理和高效的资源利用。

  • 负载均衡:在多进程架构中,可以使用负载均衡器将请求分配给多个进程,实现负载均衡。负载均衡可以提高系统的吞吐量和响应速度。

  • 分布式架构:在分布式架构中,多个Node.js进程可以在不同的机器或容器中运行,实现分布式处理和扩展。分布式架构可以提高系统的可扩展性和可靠性。

需要注意的是,多进程架构也带来了一些挑战。例如,进程间通信会增加系统的复杂性和开销;负载均衡器需要合理地分配请求,避免过载或空闲;分布式架构需要考虑如何同步数据和保证一致性等问题。

创建子进程- 9.1.3 -

child_process模块是Node.js中用于创建子进程的模块。通过child_process模块,Node.js应用程序可以创建新的进程,并且与这些进程进行通信。

child_process模块提供了几个用于创建子进程的函数,其中最常用的函数是child_process.spawn()和child_process.fork()。

  • child_process.spawn()函数用于创建一个新的进程,并执行指定的命令。它允许指定要执行的命令、命令参数、工作目录和环境变量等。

  • child_process.fork()函数用于创建一个新的子进程,并执行指定的模块。它基于进程间通信(IPC)来与子进程进行通信。

创建子进程后,可以使用子进程对象的方法来与子进程进行通信,例如stdin、stdout和stderr等流,以及kill()方法来终止子进程。

进程间通信- 9.1.4 -

在Node.js中,进程间通信(IPC)是一种使进程之间能够交换数据和信号的方法。Node.js中的child_process模块提供了几种方式来实现父子进程间的通信。

1. 使用.stdin、.stdout和.stderr进行通信:

当使用child_process.spawn()或child_process.fork()创建子进程时,子进程的stdin、stdout和stderr流与父进程是可用的。可以从父进程向子进程写入数据(通过stdin),从子进程读取数据(通过stdout和stderr)。

例如:

const { spawn } = require('child_process');  
const child = spawn('node', ['childScript.js']);  
  
child.stdout.on('data', (data) => {  
  console.log(`Child output: ${data}`);  
});  
  
child.stdin.write('Hello from parent');

在子进程脚本中:

process.stdin.on('data', (data) => {  
  console.log(`Received from parent: ${data}`);  
});

2. 使用.send()和.on('message')进行通信:

对于使用child_process.fork()创建的子进程,可以使用.send()方法发送消息到子进程,子进程可以使用process.on('message')监听来自父进程的消息。这种通信方式更加安全,因为数据是通过JSON对象传递的,而不是明文。

父进程:

const cp = require('child_process');  
const worker = cp.fork('workerScript.js');  
  
worker.send({ hello: 'world' });

子进程脚本:

process.on('message', (msg) => {  
  console.log(`Received from parent: ${msg.hello}`);  
});

3. 使用ipc模块:

如果项目使用的是Electron框架,那么可以使用ipc模块来在主进程和渲染进程之间进行通信。这个模块允许发送和接收消息,并且可以在发送消息时传递数据。

4. 使用socket进行通信:

除了上面提到的几种方法,还可以使用socket进行进程间通信。Socket是TCP/IP协议的一部分,可以在任何两个应用程序之间提供全双工通信。Node.js有一个内置的net模块,可以用来创建服务器和客户端。虽然socket通常用于不同机器上的进程间通信,但也可以用于同一机器上的不同进程间通信。