A Roadmap
  • Introduction
  • Roadmap
  • Basics
    • Basic Terminal Usage
      • Shell
        • 基本
        • 变量
        • 传递参数
        • 运算符
        • 命令
        • 流程控制
        • 函数
        • 输入输出重定向
    • Character Encoding
      • 字符编码
    • Data Structures & algorithms
    • Network
      • TCP/IP
      • Http/Https
        • 浏览器缓存
        • Status Code
        • GET & POST
        • HTTPS 握手过程
        • HostOnly Cookie
      • CDN
        • CDN 工作原理
    • Version Control
      • git message format
      • git commands
    • Principles
    • Design Patterns
    • Others
      • JSON
      • 正则表达式
  • Front End
    • Web Standard
      • Html
      • CSS
        • font-face 小记
        • Grid 布局简易笔记
      • Javascript
        • Ajax
          • Fetch
          • XMLHttpRequest
        • DOM
          • Selection
          • 常用 DOM 操作
          • script 标签的几个属性
        • Ecmascript
          • this 关键字
          • Event Loop
          • 隐式转换
          • Date
        • Event
          • 模拟事件
          • Others
    • Development
      • Package Management
        • npm
      • Modulization
        • 模块化机制
        • webpack 打包解析
      • Architecture
      • Build Tools
        • 如何编写一个自定义的 eslint 规则?
      • Debug
        • 移动端调试 web
      • Pre/Post Processors
      • Test
        • Jest Snapshot 使用指南
      • Type Checkers
        • TS 中 enum 的编译结果
    • Libs & frameworks
    • Platforms
      • Browser
        • Basics
          • 从输入 URL 到页面加载完成都发生了什么事情?
          • HTML 加载的过程示意图
          • 为什么读取某些属性,也会导致回流?
          • Chrome 进程模型
        • PWA
        • Compatible
        • Cross Origin
        • Performance
          • 性能检测:performance 对象
          • 性能指标
        • Others
          • 移动端 web 开发笔记
      • Server
      • Desktop Applications
      • Mobile Applications
        • Flutter 在移动端和 Web 端的技术实现
  • Back End
    • outline
    • Languages
      • Node
        • Event Loop
        • NodeJS 中的进程与线程
        • NodeJS 中的 esModule 与 commonJS
  • Clients
    • outline
    • 安装 IPA 包
  • DevOps
    • Languages
    • OS Concepts
    • Servers & terminal
  • UI & UX
    • outline
  • Others
    • Posts
      • 使用 node 爬取数据并导出到 excel
      • antd 1.x datepicker 时区问题
      • babel-transform-runtime 踩坑记录
      • lodash 按需加载注意事项
      • 记一次项目迁移的踩坑记录
      • 时区与JS中的Date对象
      • 记一次 vue + ts 开发踩坑
    • Tools
      • 个人常用的工具分享
      • tmux 简要笔记
Powered by GitBook
On this page
  • 前置阅读
  • IPC - 进程间通信
  • child_process
  • spawn
  • fork
  • cluster
  • 参考

Was this helpful?

  1. Back End
  2. Languages
  3. Node

NodeJS 中的进程与线程

PreviousEvent LoopNextNodeJS 中的 esModule 与 commonJS

Last updated 3 years ago

Was this helpful?

前置阅读

什么是进程间通信? 进程间通信(IPC,Inter-Process Communication),指至少两个进程或线程间传送数据或信号的一些技术或方法。

主要的 IPC 方法

Method

zh_CN

Short Description

文件

A record stored on disk, or a record synthesized on demand by a file server, which can be accessed by multiple processes.

Most operating systems

信号

A system message sent from one process to another, not usually used to transfer data but instead used to remotely command the partnered process.

Most operating systems

套接字

Most operating systems

消息队列

A data stream similar to a socket, but which usually preserves message boundaries. Typically implemented by the operating system, they allow multiple processes to read and write to the message queue without being directly connected to each other.

Most operating systems

管道

命名管道

A pipe that is treated like a file. Instead of using standard input and output as with an anonymous pipe, processes write to and read from a named pipe as if it were a regular file.

All POSIX systems, Windows, AmigaOS 2.0+

共享内存

All POSIX systems, Windows

child_process

  • execFile: 子进程中执行的是非 node 程序,提供一组参数后,执行的结果以回调的形式返回。

  • exec: 子进程执行的是非 node 程序,传入一串 shell 命令,执行后结果以回调的形式返回,与 execFile 不同的是 exec 可以直接执行一串 shell 命令。

  • spawn: 子进程中执行的是非 node 程序,提供一组参数后,执行的结果以流的形式返回。

  • fork: 子进程执行的是 node 程序,提供一组参数后,执行的结果以流的形式返回,与 spawn 不同,fork生成的子进程只能执行 node 应用。

除此之外,child_process 也提供了 execSync, execFileSync, spawnSync 三种同步方式执行子进程。

spawn

spawn 同样是用于执行非 node 应用,且不能直接执行 shell,与 execFile 相比,spawn 执行应用后的结果并不是执行完成后,一次性的输出的,而是以流的形式输出。对于大批量的数据输出,通过流的形式可以介绍内存的使用。

const cp = require('child_process');

// exec
cp.exec('echo hello world', (error, stdout) => {
  console.log('[exec] ' + stdout);
});

// execFile
cp.execFile('echo', ['hi', 'world'], (error, stdout) => {
  console.log('[execFile] ' + stdout);
});

// spawn
cp.spawn('npm', ['--help'], { stdio: 'inherit' });

// spawn
const echo = cp.spawn('echo', ['hello world']);
const wc = cp.spawn('wc', ['-w']);
echo.stdout.pipe(wc.stdin);
wc.stdout.pipe(process.stdout);

fork

node 中提供了 fork 方法,通过 fork 方法在单独的进程中执行 node 程序,并且通过父子间的通信,子进程接受父进程的信息,并将执行后的结果返回给父进程。

// main.js
const cp = require('child_process');
const child = cp.fork('./child.js');

console.log('[main] pid: ' + process.pid);
console.log('[main] child pid: ' + child.pid);

child.on('message', msg => {
  console.log('[main] got a message');
  console.log('[main] message: ' + msg);
});

// 监听子进程断开连接
child.on('exit', () => {
  console.log('[main] child process exited');
});

console.log('[main] sent a message');
child.send('hello world');

setTimeout(() => {
  child.disconnect();
  // process.kill(child.pid)
}, 3000);
// child.js
// 父进程 send 第一条消息时,才会开始执行子进程
console.log('[child] ppid: ' + process.ppid);
console.log('[child] pid: ' + process.pid);

process.on('message', function(msg) {
  console.log('[child] got a message');
  process.send('[child] message length is ' + msg.length);
});

setTimeout(() => {
  process.send('[child] heart beat 1');
}, 1000);

setTimeout(() => {
  process.send('[child] heart beat 2');
}, 2000);

// 监听父进程断开连接
process.on('disconnect', () => {
  console.log('[child] disconnect');
});

使用 fork 方式构建多进程 web 服务

常见问题

1. 子进程启动失败

问题原因

  • 进程拥有独立的资源,比如内存、端口

  • 根据同一个 server 配置 fork 出来的多个子进程,如果是 http server 服务,占用相同的端口,必然会报错。

解决方案

  1. 反向代理

  2. IPC 传递 socket

  3. Cluster

2. 子进程异常退出怎么办

  1. 监听子进程退出事件

    • 子进程事件机制

    • process.on('exit', callback)

  2. 退出后重新 refork 子进程

3. 孤儿进程 / 僵尸进程

父进程已退出,子进程还在运行

  1. 获取所有子进程

  2. 信号机制,守护进程监听 SIGTERM,利用 process.kill 退出所有子进程

cluster

A single instance of Node.js runs in a single thread. To take advantage of multi-core systems, the user will sometimes want to launch a cluster of Node.js processes to handle the load.

The cluster module allows easy creation of child processes that all share server ports.

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`[master] ${process.pid} is running`);

  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`[master] worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http
    .createServer((req, res) => {
      res.writeHead(200);
      res.end(`[worker:${process.pid}] hello world\n`);
    })
    .listen(8000);

  console.log(`[worker] ${process.pid} started`);
}

参考

Provided by ( or other environments)

; also

Data sent over a network interface, either to a different process on the same computer or to another computer on the network. Stream-oriented (; data written through a socket requires formatting to preserve message boundaries) or more rarely message-oriented (, ).

A unidirectional data channel utilizing . Data written to the write-end of the pipe is buffered by the operating system until it is read from the read-end of the pipe. Two-way communication between processes can be achieved by using two pipes in opposite "directions".

All systems, Windows

Multiple processes are given access to the same block of which creates a shared buffer for the processes to communicate with each other.

child_process 模块提供用以创建子进程:

四种方式
nodejs 中的子进程,深入解析 child_process 模块和 cluster 模块
Child Process
Cluster
Worker Threads
What is Node.js cluster best practice?
operating systems
File
Signal
Asynchronous System Trap
Socket
TCP
UDP
SCTP
Message queue
Anonymous pipe
standard input and output
POSIX
Named pipe
Shared memory
memory
IPC - 进程间通信