国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

nodejs中的子進程,深入解析child_process模塊和cluster模塊

JinB / 2391人閱讀

摘要:嚴格來說,并不是單線程的。其他異步和事件驅動相關的線程通過來實現內部的線程池和線程調度。線程是最小的進程,因此也是單進程的。子進程中執行的是非程序,提供一組參數后,執行的結果以回調的形式返回。在子進程中通過和的機制來接收和發送消息。

??node遵循的是單線程單進程的模式,node的單線程是指js的引擎只有一個實例,且在nodejs的主線程中執行,同時node以事件驅動的方式處理IO等異步操作。node的單線程模式,只維持一個主線程,大大減少了線程間切換的開銷。

??但是node的單線程使得在主線程不能進行CPU密集型操作,否則會阻塞主線程。對于CPU密集型操作,在node中通過child_process可以創建獨立的子進程,父子進程通過IPC通信,子進程可以是外部應用也可以是node子程序,子進程執行后可以將結果返回給父進程。

??此外,node的單線程,以單一進程運行,因此無法利用多核CPU以及其他資源,為了調度多核CPU等資源,node還提供了cluster模塊,利用多核CPU的資源,使得可以通過一串node子進程去處理負載任務,同時保證一定的負載均衡型。本文從node的單線程單進程的理解觸發,介紹了child_process模塊和cluster模塊,本文的結構安排如下:

node中的單線程和單進程

node中的child_process模塊實現多進程

node中的cluster模塊

總結

原文的地址,在我的博客中:https://github.com/forthealll...

如有幫助,您的star是對我最好的鼓勵~

一、node中的單線程和單進程

??首先要理解的概念是,node的單線程和單進程的模式。node的單線程于其他語言的多線程模式相比,減小了線程間切換的開銷,以及在寫node代碼的時候不用考慮鎖以及線程池的問題。node宣稱的單線程模式,比其他語言更加適合IO密集型操作。那么一個經典的問題是:

node是真的單線程的嗎?

提到node,我們就可以立刻想到單線程、異步IO、事件驅動等字眼。首先要明確的是node真的是單線程的嗎,如果是單線程的,那么異步IO,以及定時事件(setTimeout、setInterval等)又是在哪里被執行的。

嚴格來說,node并不是單線程的。node中存在著多種線程,包括:

js引擎執行的線程

定時器線程(setTimeout, setInterval)

異步http線程(ajax)

....

??我們平時所說的單線程是指node中只有一個js引擎在主線程上運行。其他異步IO和事件驅動相關的線程通過libuv來實現內部的線程池和線程調度。libv中存在了一個Event Loop,通過Event Loop來切換實現類似于多線程的效果。簡單的來講Event Loop就是維持一個執行棧和一個事件隊列,當前執行棧中的如果發現異步IO以及定時器等函數,就會把這些異步回調函數放入到事件隊列中。當前執行棧執行完成后,從事件隊列中,按照一定的順序執行事件隊列中的異步回調函數。

上圖中從執行棧,到事件隊列,最后事件隊列中按照一定的順序執行回調函數,整個過程就是一個簡化版的Event Loop。此外回調函數執行時,同樣會生成一個執行棧,在回調函數里面還有可能嵌套異步的函數,也就是說執行棧存在著嵌套。

也就是說node中的單線程是指js引擎只在唯一的主線程上運行,其他的異步操作,也是有獨立的線程去執行,通過libv的Event Loop實現了類似于多線程的上下文切換以及線程池調度。線程是最小的進程,因此node也是單進程的。這樣就解釋了為什么node是單線程和單進程的。

二、node中的child_process模塊實現多進程

??node是單進程的,必然存在一個問題,就是無法充分利用cpu等資源。node提供了child_process模塊來實現子進程,從而實現一個廣義上的多進程的模式。通過child_process模塊,可以實現1個主進程,多個子進程的模式,主進程稱為master進程,子進程又稱工作進程。在子進程中不僅可以調用其他node程序,也可以執行非node程序以及shell命令等等,執行完子進程后,以流或者回調的形式返回。

1、child_process模塊提供的API

child_process提供了4個方法,用于新建子進程,這4個方法分別為spawn、execFile、exec和fork。所有的方法都是異步的,可以用一張圖來描述這4個方法的區別。

上圖可以展示出這4個方法的區別,我們也可以簡要介紹這4中方法的不同。

spawn : 子進程中執行的是非node程序,提供一組參數后,執行的結果以流的形式返回。

execFile:子進程中執行的是非node程序,提供一組參數后,執行的結果以回調的形式返回。

exec:子進程執行的是非node程序,傳入一串shell命令,執行后結果以回調的形式返回,與execFile
不同的是exec可以直接執行一串shell命令。

fork:子進程執行的是node程序,提供一組參數后,執行的結果以流的形式返回,與spawn不同,fork生成的子進程只能執行node應用。接下來的小節將具體的介紹這一些方法。

2、execFile和exec

我們首先比較execFile和exec的區別,這兩個方法的相同點:

執行的是非node應用,且執行后的結果以回調函數的形式返回。

不同點是:

exec是直接執行的一段shell命令,而execFile是執行的一個應用

舉例來說,echo是UNIX系統的一個自帶命令,我們直接可以在命令行執行:

echo hello world

結果,在命令行中會打印出hello world.

(1) 通過exec來實現

新建一個main.js文件中,如果要使用exec方法,那么則在該文件中寫入:

let cp=require("child_process");
cp.exec("echo hello world",function(err,stdout){
  console.log(stdout);
});

執行這個main.js,結果會輸出hello world。我們發現exec的第一個參數,跟shell命令完全相似。

(2)通過execFile來實現
let cp=require("child_process");
cp.execFile("echo",["hello","world"],function(err,stdout){
   console.log(stdout);
});

execFile類似于執行了名為echo的應用,然后傳入參數。execFlie會在process.env.PATH的路徑中依次尋找是否有名為"echo"的應用,找到后就會執行。默認的process.env.PATH路徑中包含了"usr/local/bin",而這個"usr/local/bin"目錄中就存在了這個名為"echo"的程序,傳入hello和world兩個參數,執行后返回。

(3)安全性分析

像exec那樣,可以直接執行一段shell是極為不安全的,比如有這么一段shell:

echo hello world;rm -rf

通過exec是可以直接執行的,rm -rf會刪除當前目錄下的文件。exec正如命令行一樣,執行的等級很高,執行后會出現安全性的問題,而execFile不同:

execFile("echo",["hello","world",";rm -rf"])

在傳入參數的同時,會檢測傳入實參執行的安全性,如果存在安全性問題,會拋出異常。除了execFile外,spawn和fork也都不能直接執行shell,因此安全性較高。

3、spawn

spawn同樣是用于執行非node應用,且不能直接執行shell,與execFile相比,spawn執行應用后的結果并不是執行完成后,一次性的輸出的,而是以流的形式輸出。對于大批量的數據輸出,通過流的形式可以介紹內存的使用。

我們用一個文件的排序和去重來舉例:

上述圖片示意圖中,首先讀取的input.txt文件中有acba未經排序的文字,通過sort程序后可以實現排序功能,輸出為aabc,最后通過uniq程序可以去重,得到abc。我們可以用spawn流形式的輸入輸出來實現上述功能:

let cp=require("child_process");
let cat=cp.spawn("cat",["input.txt"]);
let sort=cp.spawn("sort");
let uniq=cp.spawn("uniq");

cat.stdout.pipe(sort.stdin);
sort.stdout.pipe(uniq.stdin);
uniq.stdout.pipe(process.stdout);
console.log(process.stdout);

執行后,最后的結果將輸入到process.stdout中。如果input.txt這個文件較大,那么以流的形式輸入輸出可以明顯減小內存的占用,通過設置緩沖區的形式,減小內存占用的同時也可以提高輸入輸出的效率。

4、fork

在javascript中,在處理大量計算的任務方面,HTML里面通過web work來實現,使得任務脫離了主線程。在node中使用了一種內置于父進程和子進程之間的通信來處理該問題,降低了大數據運行的壓力。node中提供了fork方法,通過fork方法在多帶帶的進程中執行node程序,并且通過父子間的通信,子進程接受父進程的信息,并將執行后的結果返回給父進程。

使用fork方法,可以在父進程和子進程之間開放一個IPC通道,使得不同的node進程間可以進行消息通信。

在子進程中:

通過process.on("message")和process.send()的機制來接收和發送消息。

在父進程中:

通過child.on("message")和process.send()的機制來接收和發送消息。

具體例子,在child.js中:

process.on("message",function(msg){
   process.send(msg)
})

在parent.js中:

let cp=require("child_process");
let child=cp.fork("./child");
child.on("message",function(msg){
  console.log("got a message is",msg);
});
child.send("hello world");

執行parent.js會在命令行輸出:got a message is hello world

中斷父子間通信的方式,可以通過在父進程中調用:

child.disconnect()

來實現斷開父子間IPC通信。

5、同步執行的子進程

exec、execFile、spawn和fork執行的子進程都是默認異步的,子進程的運行不會阻塞主進程。除此之外,child_process模塊同樣也提供了execFileSync、spawnSync和execSync來實現同步的方式執行子進程。

三、node中的cluster模塊

cluster意為集成,集成了兩個方面,第一個方面就是集成了child_process.fork方法創建node子進程的方式,第二個方面就是集成了根據多核CPU創建子進程后,自動控制負載均衡的方式。

我們從官網的例子來看:

const cluster = require("cluster");
const http = require("http");
const numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
  console.log(`主進程 ${process.pid} 正在運行`);

  // 衍生工作進程。
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on("exit", (worker, code, signal) => {
    console.log(`工作進程 ${worker.process.pid} 已退出`);
  });
} else {
  // 工作進程可以共享任何 TCP 連接。
  // 在本例子中,共享的是一個 HTTP 服務器。
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end("你好世界
");
  }).listen(8000);

  console.log(`工作進程 ${process.pid} 已啟動`);
}

最后輸出的結果為:

$ node server.js
主進程 3596 正在運行
工作進程 4324 已啟動
工作進程 4520 已啟動
工作進程 6056 已啟動
工作進程 5644 已啟動

我們將master稱為主進程,而worker進程稱為工作進程,利用cluster模塊,使用node封裝好的API、IPC通道和調度機可以非常簡單的創建包括一個master進程下HTTP代理服務器 + 多個worker進程多個HTTP應用服務器的架構。

總結

本文首先介紹了node的單線程和單進程模式,接著從單線程的缺陷觸發,介紹了node中如何實現子進程的方法,對比了child_process模塊中幾種不同的子進程生成方案,最后簡單介紹了內置的可以實現子進程以及CPU進程負載均衡的內置集成模塊cluster。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97086.html

相關文章

  • 深入淺出nodeJS - 4 - (玩轉進程、測試、產品化)

    摘要:進程間通信的目的是為了讓不同的進程能夠互相訪問資源,并進程協調工作。這個過程的示意圖如下端口共同監聽集群穩定之路進程事件自動重啟負載均衡狀態共享模塊工作原理事件二測試單元測試性能測試三產品化項目工程化部署流程性能日志監控報警穩定性異構共存 內容 9.玩轉進程10.測試11.產品化 一、玩轉進程 node的單線程只不過是js層面的單線程,是基于V8引擎的單線程,因為,V8的緣故,前后...

    henry14 評論0 收藏0
  • 深入理解Node.js 進程與線程(8000長文徹底搞懂)

    摘要:在單核系統之上我們采用單進程單線程的模式來開發。由進程來管理所有的子進程,主進程不負責具體的任務處理,主要工作是負責調度和管理。模塊與模塊總結無論是模塊還是模塊,為了解決實例單線程運行,無法利用多核的問題而出現的。 前言 進程與線程是一個程序員的必知概念,面試經常被問及,但是一些文章內容只是講講理論知識,可能一些小伙伴并沒有真的理解,在實際開發中應用也比較少。本篇文章除了介紹概念,通過...

    Harpsichord1207 評論0 收藏0
  • nodeJS進程

    摘要:通過將的給出來的進程。恩吞吐率關于吞吐率有多種解讀,一種是描繪服務器單位時間處理請求的能力。而根據這個描述的話他的單位就為而這個指標就是上面數據中的當然,肯定是越大越好了吞吐量這個和上面的吞吐率很有點關系的。 首先鄭重聲明:nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言! 重要的事情說3遍。 因為...

    happen 評論0 收藏0
  • nodeJS進程

    摘要:通過將的給出來的進程。恩吞吐率關于吞吐率有多種解讀,一種是描繪服務器單位時間處理請求的能力。而根據這個描述的話他的單位就為而這個指標就是上面數據中的當然,肯定是越大越好了吞吐量這個和上面的吞吐率很有點關系的。 首先鄭重聲明:nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言! 重要的事情說3遍。 因為...

    james 評論0 收藏0
  • 初識Node.js

    摘要:一旦替換已經完成,該模塊將被完全棄用。用作錯誤處理事件文件,由在標準功能上的簡單包裝器提供所有模塊都提供這些對象。 Node.js簡介 Node 定義 Node.js是一個建立在Chrome v8 引擎上的javascript運行時環境 Node 特點 異步事件驅動 showImg(https://segmentfault.com/img/bVMLD1?w=600&h=237); no...

    lk20150415 評論0 收藏0

發表評論

0條評論

JinB

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<