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



相关文章
|
8天前
|
JavaScript 前端开发 API
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务
该文章详细讲解了队列数据结构在前端开发中的应用,并深入探讨了JavaScript的事件循环机制,区分了宏任务和微任务的执行顺序及其对前端性能的影响。
|
29天前
|
前端开发 JavaScript API
JavaScript 的宏任务和微任务有什么区别
【9月更文挑战第6天】JavaScript 的宏任务和微任务有什么区别
22 4
|
2月前
|
存储 前端开发 JavaScript
JavaScript 并发任务控制
【8月更文挑战第31天】JavaScript 并发任务控制
14 2
|
2月前
|
运维 JavaScript 安全
自动化运维:使用Ansible简化日常任务深入理解Node.js事件循环和异步编程
【8月更文挑战第27天】在快节奏的技术环境中,自动化不再是奢侈品,而是必需品。本文将引导你通过Ansible实现自动化运维,从基础到高级应用,解锁高效管理服务器群的秘诀,让你的IT操作更加流畅和高效。
|
2月前
|
Linux Perl
在Linux中,系统目前有许多正在运行的任务,在不重启机器的条件下,有什么方法可以把所有正在运行的进程移除呢?
在Linux中,系统目前有许多正在运行的任务,在不重启机器的条件下,有什么方法可以把所有正在运行的进程移除呢?
|
2月前
|
JavaScript Windows
NodeJs——如何获取Windows电脑指定应用进程信息
NodeJs——如何获取Windows电脑指定应用进程信息
69 0
|
2月前
|
JavaScript 前端开发
nodejs process进程
nodejs process进程
26 0
|
3月前
|
JavaScript IDE 持续交付
阿里云云效产品使用合集之如何配置 Node.js构建任务让其在Windows环境中进行
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
3月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的校园悬赏任务平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的校园悬赏任务平台附带文章源码部署视频讲解等
30 0
|
3月前
|
JavaScript 前端开发 API
js 运行机制(含异步机制、同步任务、异步任务、宏任务、微任务、Event Loop)
js 运行机制(含异步机制、同步任务、异步任务、宏任务、微任务、Event Loop)
32 0