Node.js使用多進(jìn)程提高任務(wù)執(zhí)行效率
最近我有個(gè)學(xué)員寫了個(gè) Node.js 腳本程序,定時(shí)從某個(gè)服務(wù)器下載文件,并向另一個(gè)云服務(wù)商上傳文件。
但是每次只能先下載一個(gè)文件,再去上傳一個(gè)文件。效率比較低。于是他向我請(qǐng)教,怎么樣才能提高效率?我告訴他應(yīng)該用 Node 的多進(jìn)程技術(shù)。
什么是 Node 多進(jìn)程?
Node 是在單個(gè)線程中運(yùn)行,我們雖然沒辦法開啟額外的線程,但是可以開啟進(jìn)程集群。這樣可以讓下載任務(wù)和上傳任務(wù)同時(shí)進(jìn)行。
使用多進(jìn)程進(jìn)行初步代碼優(yōu)化
簡(jiǎn)單看了一下學(xué)員的代碼,大概是這樣:
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()這個(gè)代碼邏輯上是沒問(wèn)題的,但是它只能在 1 個(gè) CPU 核心中運(yùn)行。
我們完全可以使用 Node.js 的多進(jìn)程來(lái)利用 CPU 的多核心來(lái)增加這個(gè)程序的吞吐量。
怎么改造呢?
也非常簡(jiǎn)單。
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 模塊可以告訴我們運(yùn)行環(huán)境的 CPU 信息,我們可以通過(guò)它來(lái)做為創(chuàng)建進(jìn)程數(shù)量的限制條件。然后通過(guò) cluster.isMaster 來(lái)判斷是否是主進(jìn)程,因?yàn)橹挥兄鬟M(jìn)程才擁有 fork 的能力。
worker和master通信
其實(shí)上面的代碼還可以繼續(xù)做更深層次的優(yōu)化,仔細(xì)分析一下,下載速度和上傳速度其實(shí)是不一致的。通常來(lái)說(shuō),下載速度會(huì)很慢,但上傳速度會(huì)很快。我們可以讓其他進(jìn)程去下載文件,當(dāng)下載成功之后,讓主進(jìn)程去上傳文件。
Node 中的多進(jìn)程之間不會(huì)共享內(nèi)存,所以我們可以通過(guò)消息傳遞的方式,讓下載進(jìn)程通知主進(jìn)程去上傳文件。
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()可以在主進(jìn)程中通過(guò) worker.on('message', (msg)=>{}) 的方式來(lái)監(jiān)聽子進(jìn)程發(fā)送的消息。在子進(jìn)程中通過(guò) process.send 來(lái)向主進(jìn)程發(fā)送消息。
總結(jié)
在 NodeJS 中使用多進(jìn)程非常簡(jiǎn)單,合理使用多進(jìn)程,可以解放硬件的能力,讓軟件的運(yùn)行效率得到肉眼可見的提升。
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
win10環(huán)境使用nvm安裝多版本nodejs并配置環(huán)境變量的完整步驟
這篇文章主要給大家介紹了關(guān)于win10環(huán)境使用nvm安裝多版本nodejs并配置環(huán)境變量的相關(guān)資料,需要的朋友可以參考下2024-01-01
使用nodejs實(shí)現(xiàn)JSON文件自動(dòng)轉(zhuǎn)Excel的工具(推薦)
這篇文章主要介紹了使用nodejs實(shí)現(xiàn),JSON文件自動(dòng)轉(zhuǎn)Excel的工具,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
node-sass安裝失敗解決方法總結(jié)(終有一款適合你)
node-sass是我們開發(fā)中很常見的依賴包,也是安裝時(shí)間冗長(zhǎng)和最常見到報(bào)錯(cuò)的依賴,下面這篇文章主要給大家介紹了關(guān)于node-sass安裝失敗解決方法的相關(guān)資料,需要的朋友可以參考下2022-11-11
使用Koa實(shí)現(xiàn)一個(gè)獲取視頻播放地址的接口
在本節(jié)課中,我們將學(xué)習(xí)如何使用 Koa 實(shí)現(xiàn)一個(gè)獲取視頻播放地址的接口,我們將創(chuàng)建一個(gè)控制器,通過(guò)視頻 ID 獲取播放地址,并設(shè)置相應(yīng)的路由,最后,我們將使用 Postman 進(jìn)行測(cè)試,感興趣的朋友可以參考下2024-05-05
node.js中的buffer.toJSON方法使用說(shuō)明
這篇文章主要介紹了node.js中的buffer.toJSON方法使用說(shuō)明,本文介紹了buffer.toJSON的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12
Node.js中fs模塊實(shí)現(xiàn)配置文件的讀寫操作
在Node.js中, fs模塊提供了對(duì)文件系統(tǒng)的訪問(wèn)功能,我們可以利用它來(lái)實(shí)現(xiàn)配置文件的讀取和寫入操作,這篇文章主要介紹了Node.js中fs模塊實(shí)現(xiàn)配置文件的讀寫,需要的朋友可以參考下2024-04-04
Express服務(wù)器端代碼熱加載的實(shí)現(xiàn)代碼
這篇文章主要介紹了Express服務(wù)器端代碼熱加載的實(shí)現(xiàn),文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-01-01

