Node JS 多进程
在 Node.js 中,可以使用多个进程来处理文件,并发执行任务以提高性能和效率。多进程可以提高应用程序的性能和可靠性,但同时也会带来一些额外的开销和复杂性问题
优点
可以高效利用多核 CPU ,将许多并发请求分配到不同的进程中处理,来提高应用程序性能。
提高可靠性,多进程互相隔离,当一个进程崩溃或出现问题时,其他进程应该能够继续工作,不会影响整个应用程序的运行。
缺点
多进程开销更大,需要更多的内存和 CPU 资源来维护进程通信和进程间数据同步。
多进程本身就是一种分布式运行模式,会增加维护和调试难度
进程间通信和信息同步复杂,可能导致性能与内存问题。
具体有两种方式:
- 使用
child_process
模块:child_process
模块允许你创建子进程并与其进行通信。你可以使用child_process.fork()
方法创建多个子进程,每个子进程负责处理一个文件或一组文件。通过进程间的消息传递,我们可以在主进程和子进程之间共享数据和任务。这种方式适用于文件处理任务比较独立且相互之间没有太多的依赖关系的情况。 - 使用进程池:进程池是一组预先创建的子进程,可以通过将任务分配给空闲的子进程来提高处理能力。我们可以使用
worker_threads
模块来创建进程池。
下面实例中分别使用了child_process(async_process 方法)创建子进程与worker_threads(assignTaskToWorkers 方法)创建进程池:
process.js:
import ipcMain from '../ipcMain'; const { fork } = require('child_process'); const { Worker } = require('worker_threads'); const path = require('path'); class FileProcess { constructor() { this.process = null; this.workerPool = new Set(); ipcMain.ipc.on("async_update_file", this.async_update_file.bind(this)) } async_update_file(event, arg) { const files = arg.files; if(files.length === 1) { this.async_process(files[0]); } else { this.assignTaskToWorkers(files); } } async_process(file) { // 创建子进程 const childPath = path.join(process.cwd(), '/src/main/process/fileProcessor.js'); const child = fork(childPath); // 向子进程发送消息 child.send(file); // 监听子进程的消息 child.on('message', (data) => { console.log(`子进程返回结果:${data}`); }); // 监听子进程的错误 child.on('error', (error) => { console.error(`子进程发生错误:${error}`); }); } // 添加任务到进程池 addToWorkerPool(file) { const childPath = path.join(process.cwd(), '/src/main/process/fileWorker.js'); const worker = new Worker(childPath, { workerData: file }); worker.on('message', (data) => { console.log(`子进程返回结果:${data}`); this.workerPool.delete(worker); worker.unref(); }); worker.on('error', (error) => { console.error(`子进程发生错误:${error}`); this.workerPool.delete(worker); worker.unref(); }); this.workerPool.add(worker); // console.log('this.workerPool', this.workerPool) } // 分配任务到进程池 assignTaskToWorkers(files) { files.forEach((file) => this.addToWorkerPool(file)); } } export default FileProcess;
fileProcessor.js
const fs = require('fs'); process.on('message', (file) => { console.log('file=======', file) // 处理文件 try { const data = fs.readFileSync(file, 'utf8'); const processedData = processData(data); process.send(processedData); } catch (error) { process.send(`文件处理出错:${error.message}`); } }); function processData(data) { // 进行文件处理逻辑示例 return data.toUpperCase(); }
fileWorker.js
const { workerData, parentPort } = require('worker_threads'); const fs = require('fs'); // 读取 workerData 中指定的文件 const file = fs.readFileSync(workerData, 'utf8'); // 处理数据(此处只是简单地转换为大写字母) const upperCaseData = file.toUpperCase(); // 返回处理结果 parentPort.postMessage(upperCaseData);
async_process