一文聊聊node的多程序和多執行緒

2022-02-28 22:00:07
本篇文章帶大家瞭解一下node.js,介紹一下中的多程序和多執行緒,對比一下多程序和多執行緒,希望對大家有所幫助!

node.js中的多程序與多執行緒

在中,javascript程式碼的執行是單執行緒執行的,可是Node 本身其實是多執行緒的。

1.gif

node本身分為三層

第一層,Node.js 標準庫,這部分是由 Javascript編寫的,即我們使用過程中直接能呼叫的 API,在原始碼中的 lib 目錄下可以看到。

第二層,Node bindings,這一層是 Javascript 與底層 C/C++ 能夠溝通的關鍵,前者通過 bindings 呼叫後者,相互交換資料,是第一層和第三層的橋樑。

第三層,是支撐 Node.js 執行的關鍵,由 C/C++ 實現,是node實現的一些底層邏輯。

其中,第三層的Libuv,為 Node.js 提供了跨平臺,執行緒池,事件池,非同步 I/O 等能力,是 Node.js 如此強大的關鍵。

由於Libuv提供了事件迴圈機制,所以在io處理方面,javascript並不會發生阻塞,所以我們用node搭建web服務時,並不需要擔心io量過大,導致其他請求阻塞。

可是,非io任務的執行,是在node主執行緒中執行的,是單執行緒執行任務,如果有非常消耗時間的同步計算任務,將會阻塞其他程式碼的執行。

const Koa = require('koa');
const app = new Koa();

app.use(async (ctx) => {
    const url = ctx.request.url;
    if (url === '/') {
        ctx.body = {name: 'xxx', age: 14}
    }
    if(url==='/compute'){
        let sum=0
        for (let i = 0; i <100000000000 ; i++) {
        sum+=i    
        }
        ctx.body={sum}
    }
})
app.listen(4000, () => {
    console.log('http://localhost:4000/ start')
})

上面這串程式碼,如果http請求了 /compute ,node會呼叫cpu進行大量的計算,這時如果有其他http請求進入,將會發生阻塞。

那麼如何解決這個問題呢?

有兩種方案,一種是使用children_process或者cluster開啟多程序進行計算,一種是使用worker_thread 開啟多執行緒進行計算

多程序 vs 多執行緒

對比一下多執行緒與多程序:

屬性多程序多執行緒比較
資料資料共用複雜,需要用IPC;資料是分開的,同步簡單因為共用程序資料,資料共用簡單,同步複雜各有千秋
CPU、記憶體佔用記憶體多,切換複雜,CPU利用率低佔用記憶體少,切換簡單,CPU利用率高多執行緒更好
銷燬、切換建立銷燬、切換複雜,速度慢建立銷燬、切換簡單,速度很快多執行緒更好
coding編碼簡單、偵錯方便編碼、偵錯複雜編碼、偵錯複雜
可靠性程序獨立執行,不會相互影響執行緒同呼吸共命運多程序更好
分散式可用於多機多核分散式,易於擴充套件只能用於多核分散式多程序更好

採用多執行緒來解決上面程式碼的計算問題:

//api.js
const Koa = require('koa');
const app = new Koa();

const {Worker} = require('worker_threads')
app.use(async (ctx) => {
    const url = ctx.request.url;
    if (url === '/') {
        ctx.body = {name: 'xxx', age: 14}
    }

    if (url === '/compute') {
        const sum = await new Promise(resolve => {
            const worker = new Worker(__dirname+'/compute.js')
          //接收資訊
            worker.on('message', data => {
                resolve(data)
            })
        })
        ctx.body = {sum}

    }
})
app.listen(4000, () => {
    console.log('http://localhost:4000/ start')
})



//computer.js
const {parentPort}=require('worker_threads')
let sum=0
for (let i = 0; i <1000000000 ; i++) {
    sum+=i
}
//傳送資訊
parentPort.postMessage(sum)

這裡是官方檔案,worker_threads

https://nodejs.org/dist/latest-v16.x/docs/api/worker_threads.html

採用多程序來解決上面程式碼的計算問題:

//api.js
const Koa = require('koa');
const app = new Koa();
const {fork} = require('child_process')

app.use(async (ctx) => {
    const url = ctx.request.url;
    if (url === '/') {
        ctx.body = {name: 'xxx', age: 14}
    }

    if (url === '/compute') {
        const sum = await new Promise(resolve => {
          const worker =fork(__dirname+'/compute.js')
            worker.on('message', data => {
                resolve(data)
            })
        })
        ctx.body = {sum}

    }
})
app.listen(4000, () => {
    console.log('http://localhost:4000/ start')
})

//computer.js
let sum=0
for (let i = 0; i <1000000000 ; i++) {
    sum+=i
}
process.send(sum)

這裡是官方檔案,child_process

https://nodejs.org/dist/latest-v16.x/docs/api/child_process.html

更多node相關知識,請存取:!

以上就是一文聊聊node的多程序和多執行緒的詳細內容,更多請關注TW511.COM其它相關文章!