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

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

最近我有个学员写了个 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 中使用多进程非常简单,合理使用多进程,可以解放硬件的能力,让软件的运行效率得到肉眼可见的提升。



相关文章
|
2月前
|
缓存 JavaScript Unix
Node.js 多进程
10月更文挑战第8天
35 0
|
3月前
|
JavaScript 前端开发 API
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务
该文章详细讲解了队列数据结构在前端开发中的应用,并深入探讨了JavaScript的事件循环机制,区分了宏任务和微任务的执行顺序及其对前端性能的影响。
|
18天前
|
数据可视化 项目管理
甘特图是什么?任务进程管理神器
甘特图是项目管理中的可视化工具,通过时间轴与任务列表展现项目进度和任务分配,支持任务间的依赖关系和里程碑设置,适用于项目管理、团队协作、日常任务安排及科研计划等多种场景,有效提升项目管理和团队协作效率。
45 4
|
1月前
|
运维 监控 JavaScript
鸿蒙next版开发:分析JS Crash(进程崩溃)
在HarmonyOS 5.0中,JS Crash指未处理的JavaScript异常导致应用意外退出。本文详细介绍如何分析JS Crash,包括异常捕获、日志分析和典型案例,帮助开发者定位问题、修复错误,提升应用稳定性。通过DevEco Studio收集日志,结合HiChecker工具,有效解决JS Crash问题。
50 4
|
2月前
|
JavaScript 前端开发 调度
在JavaScript中异步任务里的微任务和宏任务的特点和生命周期
在JavaScript中异步任务里的微任务和宏任务的特点和生命周期
46 0
|
3月前
|
前端开发 JavaScript API
JavaScript 的宏任务和微任务有什么区别
【9月更文挑战第6天】JavaScript 的宏任务和微任务有什么区别
92 4
|
4月前
|
存储 前端开发 JavaScript
JavaScript 并发任务控制
【8月更文挑战第31天】JavaScript 并发任务控制
52 2
|
4月前
|
运维 JavaScript 安全
自动化运维:使用Ansible简化日常任务深入理解Node.js事件循环和异步编程
【8月更文挑战第27天】在快节奏的技术环境中,自动化不再是奢侈品,而是必需品。本文将引导你通过Ansible实现自动化运维,从基础到高级应用,解锁高效管理服务器群的秘诀,让你的IT操作更加流畅和高效。
|
1月前
|
Web App开发 JavaScript 前端开发
2024年5月node.js安装(winmac系统)保姆级教程
本篇博客为2024年5月版Node.js安装教程,适用于Windows和Mac系统。作者是一名熟悉JavaScript与Vue的大一学生,分享了Node.js的基本介绍、下载链接及简单安装步骤。安装完成后,通过终端命令`node -v`验证版本即可确认安装成功。欢迎关注作者,获取更多技术文章。
28 2
2024年5月node.js安装(winmac系统)保姆级教程
下一篇
DataWorks