使用 Node.js 多进程提高任务执行效率

开发
在 NodeJS 中使用多进程非常简单,合理使用多进程,可以解放硬件的能力,让软件的运行效率得到肉眼可见的提升。

最近我有个学员写了个 Node.js 脚本程序,定时从某个服务器下载文件,并向另一个云服务商上传文件。

但是每次只能先下载一个文件,再去上传一个文件。效率比较低。于是他向我请教,怎么样才能提高效率?我告诉他应该用 Node 的多进程技术。

什么是 Node 多进程?

Node 是在单个线程中运行,我们虽然没办法开启额外的线程,但是可以开启进程集群。这样可以让下载任务和上传任务同时进行。

使用多进程进行初步代码优化

简单看了一下学员的代码,大概是这样:

const dl = require('./download.js')
const ul = require('./upload.js')
const source = require('./source.js')

async function runTask() {
const { originUrl, targetUrl } = source.getNext()
const { data } = await dl(originUrl)
await ul(targetUrl, data)
runTask()
}

runTask()

这个代码逻辑上是没问题的,但是它只能在 1 个 CPU 核心中运行。

我们完全可以使用 Node.js 的多进程来利用 CPU 的多核心来增加这个程序的吞吐量。

怎么改造呢?

也非常简单。

const os = require('os')
const cluster = require('cluster')
const dl = require('./download.js')
const ul = require('./upload.js')
const source = require('./source.js')

function run() {
if(cluster.isMaster) {
const numCPUs = os.cpus().length;
for(let idx = 0; idx < numCPUs; idx++) {
cluster.fork();
}
} else {
runTask()
}
}

async function runTask() {
const { originUrl, targetUrl } = source.getNext()
const { data } = await dl(originUrl)
await ul(targetUrl, data)
runTask()
}
}

run()

在上面的代码中,我添加了 os 和 cluster 模块。os 模块可以告诉我们运行环境的 CPU 信息,我们可以通过它来做为创建进程数量的限制条件。然后通过 cluster.isMaster 来判断是否是主进程,因为只有主进程才拥有 fork 的能力。

worker 和 master 通信

其实上面的代码还可以继续做更深层次的优化,仔细分析一下,下载速度和上传速度其实是不一致的。通常来说,下载速度会很慢,但上传速度会很快。我们可以让其他进程去下载文件,当下载成功之后,让主进程去上传文件。

Node 中的多进程之间不会共享内存,所以我们可以通过消息传递的方式,让下载进程通知主进程去上传文件。

const os = require('os')
const cluster = require('cluster')
const dl = require('./download.js')
const ul = require('./upload.js')
const source = require('./source.js')

function run() {
if(cluster.isMaster) {
const numCPUs = os.cpus().length;
for(let idx = 0; idx < numCPUs; idx++) {
const worker = cluster.fork();
worker.on('message', ({ targetUrl, data }) => {
ul(targetUrl, data)
})
}
} else {
runTask()
}
}

async function runTask() {
const { originUrl, targetUrl } = source.getNext()
const { data } = await dl(originUrl)
process.send({ targetUrl, data })
runTask()
}

run()

可以在主进程中通过 worker.on('message', (msg)=>{}) 的方式来监听子进程发送的消息。在子进程中通过 process.send 来向主进程发送消息。

总结

在 NodeJS 中使用多进程非常简单,合理使用多进程,可以解放硬件的能力,让软件的运行效率得到肉眼可见的提升。

责任编辑:赵宁宁 来源: 稀土掘金
相关推荐

2022-09-04 15:54:10

Node.jsAPI技巧

2021-12-25 22:29:57

2022-06-13 15:59:13

Node.jsNodeJs

2022-04-02 06:04:03

Node.js代码缓存V8

2022-05-27 10:19:59

2021-08-04 23:30:28

2021-04-20 12:39:52

2021-05-21 09:36:42

开发技能代码

2017-06-15 16:44:09

Node.js框架Web 应用

2019-03-29 16:40:02

Node.js多线程前端

2011-11-10 08:55:00

Node.js

2020-01-15 14:20:07

Node.js应用程序javascript

2017-03-20 13:43:51

Node.js内存泄漏

2017-03-19 16:40:28

漏洞Node.js内存泄漏

2021-03-13 12:54:50

Node进程Cron

2021-02-10 07:38:43

Node.js后端框架

2017-11-27 11:59:40

Node.JSChrome调试程序

2014-08-28 09:35:32

Node.js前端开发

2012-10-24 14:56:30

2020-10-23 06:40:31

Node.js前端开发
点赞
收藏

51CTO技术栈公众号