From 04a86d347c1ba845f82076433f210beee5e7bc5d Mon Sep 17 00:00:00 2001 From: user Date: Tue, 19 Apr 2016 18:48:45 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E6=9D=8E=E6=B1=B6=E6=98=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python-book | 1 + 1 file changed, 1 insertion(+) create mode 160000 python-book diff --git a/python-book b/python-book new file mode 160000 index 0000000..0a2cd21 --- /dev/null +++ b/python-book @@ -0,0 +1 @@ +Subproject commit 0a2cd219c058a43d0a0f05aecb44821dd257adaf From c8d8732ecdd4379f49ef6d557e986bf78b99af4d Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 21:24:48 +0800 Subject: [PATCH 02/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f3af409..25eccce 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Nodejs-Book 本書由NUTC IMAC團隊整理與製作,由於Node的特性有事件驅動與非同步執行等特性,並且非組塞模式I/O的特性,讓Node能夠在極低的資源底下提供高性能的負載能力,在現今的雲端平台Node也是不可或缺的角色之一。 - - + + ##參與貢獻 如果您想一起參與貢獻,可以參閱以下說明: @@ -18,12 +18,83 @@ - 點選 Github [nodejs-book](https://github.com/imac-iot/nodejs-book) 並將其fork到自己的專案底下 - 在命令列輸入 git clone https://github.com/「USER_NAME」/nodejs-book -- 在修改完成後 +- 在修改完成後 - $ git add --all - $ git commit -m "Fix issue 「Your Message」" - - $ git push + - $ git push - 當做完上述步驟時再對 [nodejs-book](https://github.com/imac-iot/nodejs-book) 提出 `[new pull request]`即可完成貢獻 ##Contributor 國立台中科技大學(NUTC) IMAC 團隊 + +#Cluster +一個運行在Nodejs的單個線程中,為了充份利用多核心系統,使用者有時候要啟動Nodejs的cluster來處理負擔 + +cluster模組允許使用者容易的去創造child processes去共享server ports + +```javascript +const cluster = require('cluster'); //引入cluster函式庫 +const http = require('http'); //引入http函式庫 +const numCPUs = require('os').cpus().length; //引入os CPU 數量 + //cluster.isMaster可以判斷目前是在主程式還是在fork出去的child process +if (cluster.isMaster) { //在主程式 + // Fork workers. // + for (var i = 0; i < (numCPUs-1); i++) { //numCPUs-1是為了讓有一顆CPU可以執行系統分配或運算 + cluster.fork(); //利用cluster.fork()產生worker + } // + // + console.log('核心數:'+numCPUs); //核心數 + // + cluster.on('death', function(worker) { // + console.log('worker ' + worker.pid + ' died'); // + }); // +} else { //是child process,就直接執行伺服器程式 + // Worker processes have a http server. // + http.Server(function(req, res) { // + res.writeHead(200); // + res.end("hello world\n"); //印出hello world + }).listen(8000); //port8000 +} // + +``` +執行Nodejs 127.0.0.1:8000 + +```不知到是什麼 +$ NODE_DEBUG=cluster node server.js +23521,Master Worker 23524 online +23521,Master Worker 23526 online +23521,Master Worker 23523 online +23521,Master Worker 23528 online +``` +請注意,視窗,目前還不可能建立一個名為pipe server 的工人 + +##如何工作 +worker processes使用child_process.fork()方法所產生,以便他們可以和 parent via IPC 溝通,並透過是伺服器處理往返 +cluster模組支援分發和傳入兩個方法 +第一個(而再所有平台上默認除了windows),是round-robin 方法,其中master process在port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 + +第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 +第二個方法理論上應該的到最好的性能,然而再實踐上,分佈往往是非常不平衡的,由於操作系統的調度變幻莫測,負載經觀察,超過70%的連接在two processes 就結束了 + +因為server.listen()處理了大部分的master process工作,有三種情況,其中一般的Nodejs和cluster處理行為是不同的 + +1.server.listen({fd: 7})在master和worker通信過程,通過傳遞文件,master會監聽"文件描述為7",而不是傳遞"文件描述為7"的引用 +2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 +3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 + +cluster的各種屬性和函數 +cluster.setttings:配置cluster參數對象 +cluster.isMaster:判斷是不是master結點 +cluster.isWorker:判斷是不是worker結點 +Event: 'fork': 監聽創建worker過程事件 +Event: 'online': 監聽worker創建成功事件 +Event: 'listening': 監聽worker向master狀態事件 +Event: 'disconnect': 監聽worker中斷事件 +Event: 'exit': 監聽worker退出事件 +Event: 'setup': 監聽更新Master事件 +cluster.setupMaster([settings]): 設置cluster参数 +cluster.fork([env]): 創建worker進程 +cluster.disconnect([callback]): 關閉worket進程 +cluster.worker: 獲得當前的worker對象 +cluster.workers: 獲得cluster中所有存活的worker對象 From 653e31af8bb6141ebe4fcfbc89648fb19734e482 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 21:32:24 +0800 Subject: [PATCH 03/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 25eccce..00b7cc1 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ ##Contributor 國立台中科技大學(NUTC) IMAC 團隊 -#Cluster +##Cluster 一個運行在Nodejs的單個線程中,為了充份利用多核心系統,使用者有時候要啟動Nodejs的cluster來處理負擔 cluster模組允許使用者容易的去創造child processes去共享server ports @@ -72,6 +72,7 @@ $ NODE_DEBUG=cluster node server.js ##如何工作 worker processes使用child_process.fork()方法所產生,以便他們可以和 parent via IPC 溝通,並透過是伺服器處理往返 cluster模組支援分發和傳入兩個方法 + 第一個(而再所有平台上默認除了windows),是round-robin 方法,其中master process在port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 @@ -79,9 +80,9 @@ cluster模組支援分發和傳入兩個方法 因為server.listen()處理了大部分的master process工作,有三種情況,其中一般的Nodejs和cluster處理行為是不同的 -1.server.listen({fd: 7})在master和worker通信過程,通過傳遞文件,master會監聽"文件描述為7",而不是傳遞"文件描述為7"的引用 -2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 -3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 +- 1.server.listen({fd: 7})在master和worker通信過程,通過傳遞文件,master會監聽"文件描述為7",而不是傳遞"文件描述為7"的引用 +- 2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 +- 3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 cluster的各種屬性和函數 cluster.setttings:配置cluster參數對象 From 33846df80555d87cc677145dc6802b7be60aa8e2 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 21:34:05 +0800 Subject: [PATCH 04/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 00b7cc1..4ab7a48 100644 --- a/README.md +++ b/README.md @@ -84,18 +84,18 @@ cluster模組支援分發和傳入兩個方法 - 2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 - 3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 -cluster的各種屬性和函數 -cluster.setttings:配置cluster參數對象 -cluster.isMaster:判斷是不是master結點 -cluster.isWorker:判斷是不是worker結點 -Event: 'fork': 監聽創建worker過程事件 -Event: 'online': 監聽worker創建成功事件 -Event: 'listening': 監聽worker向master狀態事件 -Event: 'disconnect': 監聽worker中斷事件 -Event: 'exit': 監聽worker退出事件 -Event: 'setup': 監聽更新Master事件 -cluster.setupMaster([settings]): 設置cluster参数 -cluster.fork([env]): 創建worker進程 -cluster.disconnect([callback]): 關閉worket進程 -cluster.worker: 獲得當前的worker對象 -cluster.workers: 獲得cluster中所有存活的worker對象 +###cluster的各種屬性和函數 +- cluster.setttings:配置cluster參數對象 +- cluster.isMaster:判斷是不是master結點 +- cluster.isWorker:判斷是不是worker結點 +- Event: 'fork': 監聽創建worker過程事件 +- Event: 'online': 監聽worker創建成功事件 +- Event: 'listening': 監聽worker向master狀態事件 +- Event: 'disconnect': 監聽worker中斷事件 +- Event: 'exit': 監聽worker退出事件 +- Event: 'setup': 監聽更新Master事件 +- cluster.setupMaster([settings]): 設置cluster参数 +- cluster.fork([env]): 創建worker進程 +- cluster.disconnect([callback]): 關閉worket進程 +- cluster.worker: 獲得當前的worker對象 +- cluster.workers: 獲得cluster中所有存活的worker對象 From 70b03fa54e31e018e023cd522230bd6754f85f41 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 21:35:27 +0800 Subject: [PATCH 05/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4ab7a48..dd8c0ba 100644 --- a/README.md +++ b/README.md @@ -72,10 +72,8 @@ $ NODE_DEBUG=cluster node server.js ##如何工作 worker processes使用child_process.fork()方法所產生,以便他們可以和 parent via IPC 溝通,並透過是伺服器處理往返 cluster模組支援分發和傳入兩個方法 - -第一個(而再所有平台上默認除了windows),是round-robin 方法,其中master process在port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 - -第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 +- 第一個(而再所有平台上默認除了windows),是round-robin 方法,其中master process在port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 +- 第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 第二個方法理論上應該的到最好的性能,然而再實踐上,分佈往往是非常不平衡的,由於操作系統的調度變幻莫測,負載經觀察,超過70%的連接在two processes 就結束了 因為server.listen()處理了大部分的master process工作,有三種情況,其中一般的Nodejs和cluster處理行為是不同的 From 68c42323b6265f9ccda43fc546212059f6e91c4c Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 21:37:18 +0800 Subject: [PATCH 06/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dd8c0ba..b80c273 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,8 @@ if (cluster.isMaster) { //在主程式 ``` 執行Nodejs 127.0.0.1:8000 -```不知到是什麼 +``` +不知到是什麼 $ NODE_DEBUG=cluster node server.js 23521,Master Worker 23524 online 23521,Master Worker 23526 online From 907958a5b101e0e5c920ab0e7c951b677071174a Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 22:41:27 +0800 Subject: [PATCH 07/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cluster/README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 cluster/README.md diff --git a/cluster/README.md b/cluster/README.md new file mode 100644 index 0000000..1f083af --- /dev/null +++ b/cluster/README.md @@ -0,0 +1,70 @@ +##Cluster +一個運行在Nodejs的單個線程中,為了充份利用多核心系統,使用者有時候要啟動Nodejs的cluster來處理負擔 + +cluster模組允許使用者容易的去創造child processes去共享server ports + +```javascript +const cluster = require('cluster'); //引入cluster函式庫 +const http = require('http'); //引入http函式庫 +const numCPUs = require('os').cpus().length; //引入os CPU 數量 + //cluster.isMaster可以判斷目前是在主程式還是在fork出去的child process +if (cluster.isMaster) { //在主程式 + // Fork workers. // + for (var i = 0; i < (numCPUs-1); i++) { //numCPUs-1是為了讓有一顆CPU可以執行系統分配或運算 + cluster.fork(); //利用cluster.fork()產生worker + } // + // + console.log('核心數:'+numCPUs); //核心數 + // + cluster.on('death', function(worker) { // + console.log('worker ' + worker.pid + ' died'); // + }); // +} else { //是child process,就直接執行伺服器程式 + // Worker processes have a http server. // + http.Server(function(req, res) { // + res.writeHead(200); // + res.end("hello world\n"); //印出hello world + }).listen(8000); //port8000 +} // + +``` +執行Nodejs 127.0.0.1:8000 + +``` +不知到是什麼 +$ NODE_DEBUG=cluster node server.js +23521,Master Worker 23524 online +23521,Master Worker 23526 online +23521,Master Worker 23523 online +23521,Master Worker 23528 online +``` +請注意,視窗,目前還不可能建立一個名為pipe server 的工人 + +##如何工作 +worker processes使用child_process.fork()方法所產生,以便他們可以和 parent via IPC 溝通,並透過是伺服器處理往返 +cluster模組支援分發和傳入兩個方法 +- 第一個(而再所有平台上默認除了windows),是round-robin 方法,其中master process在port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 +- 第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 +第二個方法理論上應該的到最好的性能,然而再實踐上,分佈往往是非常不平衡的,由於操作系統的調度變幻莫測,負載經觀察,超過70%的連接在two processes 就結束了 + +因為server.listen()處理了大部分的master process工作,有三種情況,其中一般的Nodejs和cluster處理行為是不同的 + +- 1.server.listen({fd: 7})在master和worker通信過程,通過傳遞文件,master會監聽"文件描述為7",而不是傳遞"文件描述為7"的引用 +- 2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 +- 3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 + +###cluster的各種屬性和函數 +- cluster.setttings:配置cluster參數對象 +- cluster.isMaster:判斷是不是master結點 +- cluster.isWorker:判斷是不是worker結點 +- Event: 'fork': 監聽創建worker過程事件 +- Event: 'online': 監聽worker創建成功事件 +- Event: 'listening': 監聽worker向master狀態事件 +- Event: 'disconnect': 監聽worker中斷事件 +- Event: 'exit': 監聽worker退出事件 +- Event: 'setup': 監聽更新Master事件 +- cluster.setupMaster([settings]): 設置cluster参数 +- cluster.fork([env]): 創建worker進程 +- cluster.disconnect([callback]): 關閉worket進程 +- cluster.worker: 獲得當前的worker對象 +- cluster.workers: 獲得cluster中所有存活的worker對象 From 60b686f3894f98eebc7bb979dc791d2114054422 Mon Sep 17 00:00:00 2001 From: user Date: Mon, 2 May 2016 22:44:50 +0800 Subject: [PATCH 08/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 71 ------------------------------------------------------- 1 file changed, 71 deletions(-) diff --git a/README.md b/README.md index b80c273..5e620ff 100644 --- a/README.md +++ b/README.md @@ -27,74 +27,3 @@ ##Contributor 國立台中科技大學(NUTC) IMAC 團隊 - -##Cluster -一個運行在Nodejs的單個線程中,為了充份利用多核心系統,使用者有時候要啟動Nodejs的cluster來處理負擔 - -cluster模組允許使用者容易的去創造child processes去共享server ports - -```javascript -const cluster = require('cluster'); //引入cluster函式庫 -const http = require('http'); //引入http函式庫 -const numCPUs = require('os').cpus().length; //引入os CPU 數量 - //cluster.isMaster可以判斷目前是在主程式還是在fork出去的child process -if (cluster.isMaster) { //在主程式 - // Fork workers. // - for (var i = 0; i < (numCPUs-1); i++) { //numCPUs-1是為了讓有一顆CPU可以執行系統分配或運算 - cluster.fork(); //利用cluster.fork()產生worker - } // - // - console.log('核心數:'+numCPUs); //核心數 - // - cluster.on('death', function(worker) { // - console.log('worker ' + worker.pid + ' died'); // - }); // -} else { //是child process,就直接執行伺服器程式 - // Worker processes have a http server. // - http.Server(function(req, res) { // - res.writeHead(200); // - res.end("hello world\n"); //印出hello world - }).listen(8000); //port8000 -} // - -``` -執行Nodejs 127.0.0.1:8000 - -``` -不知到是什麼 -$ NODE_DEBUG=cluster node server.js -23521,Master Worker 23524 online -23521,Master Worker 23526 online -23521,Master Worker 23523 online -23521,Master Worker 23528 online -``` -請注意,視窗,目前還不可能建立一個名為pipe server 的工人 - -##如何工作 -worker processes使用child_process.fork()方法所產生,以便他們可以和 parent via IPC 溝通,並透過是伺服器處理往返 -cluster模組支援分發和傳入兩個方法 -- 第一個(而再所有平台上默認除了windows),是round-robin 方法,其中master process在port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 -- 第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 -第二個方法理論上應該的到最好的性能,然而再實踐上,分佈往往是非常不平衡的,由於操作系統的調度變幻莫測,負載經觀察,超過70%的連接在two processes 就結束了 - -因為server.listen()處理了大部分的master process工作,有三種情況,其中一般的Nodejs和cluster處理行為是不同的 - -- 1.server.listen({fd: 7})在master和worker通信過程,通過傳遞文件,master會監聽"文件描述為7",而不是傳遞"文件描述為7"的引用 -- 2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 -- 3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 - -###cluster的各種屬性和函數 -- cluster.setttings:配置cluster參數對象 -- cluster.isMaster:判斷是不是master結點 -- cluster.isWorker:判斷是不是worker結點 -- Event: 'fork': 監聽創建worker過程事件 -- Event: 'online': 監聽worker創建成功事件 -- Event: 'listening': 監聽worker向master狀態事件 -- Event: 'disconnect': 監聽worker中斷事件 -- Event: 'exit': 監聽worker退出事件 -- Event: 'setup': 監聽更新Master事件 -- cluster.setupMaster([settings]): 設置cluster参数 -- cluster.fork([env]): 創建worker進程 -- cluster.disconnect([callback]): 關閉worket進程 -- cluster.worker: 獲得當前的worker對象 -- cluster.workers: 獲得cluster中所有存活的worker對象 From 87c45f2ee2e4400a1786e39cb77675f2f7e228a7 Mon Sep 17 00:00:00 2001 From: user Date: Wed, 4 May 2016 14:34:43 +0800 Subject: [PATCH 09/12] =?UTF-8?q?Fix=20issue=20=E3=80=8Ccluster=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cluster/README.md | 24 ++++- nodejs-V5110-Doc/Cluster/README.md | 137 ++++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 3 deletions(-) diff --git a/cluster/README.md b/cluster/README.md index 1f083af..f2400d6 100644 --- a/cluster/README.md +++ b/cluster/README.md @@ -30,8 +30,7 @@ if (cluster.isMaster) { //在主程式 ``` 執行Nodejs 127.0.0.1:8000 -``` -不知到是什麼 +```不知到是什麼 $ NODE_DEBUG=cluster node server.js 23521,Master Worker 23524 online 23521,Master Worker 23526 online @@ -68,3 +67,24 @@ cluster模組支援分發和傳入兩個方法 - cluster.disconnect([callback]): 關閉worket進程 - cluster.worker: 獲得當前的worker對象 - cluster.workers: 獲得cluster中所有存活的worker對象 + +###worker的各種屬性和函數:可以透過cluster.workers, cluster.worket獲得 +-worker.id: id編號 +-worker.process: ChildProcess +-worker.suicide: 在disconnect()後,判断worker是否已刪除 +-worker.send(message, [sendHandle]): master给worker發送訊息。注:worker對master發送訊息要process.send(message) +-worker.kill([signal='SIGTERM']): 刪除指定的worker +-worker.disconnect(): 中斷worker連接,讓worker消失 +-Event: 'message': 監聽master和worker的message事件 +-Event: 'online': 監聽指定的worker創建成功事件 +-Event: 'listening': 監聽master向worker狀態事件 +-Event: 'disconnect': 監聽worker中斷事件 +-Event: 'exit': 監聽worker退出事件 + +###Event: 'disconnect' +類似cluster.on('disconnect')事件 +```shell +cluster.fork().on('disconnect', () => { + // Worker has disconnected +}); +``` diff --git a/nodejs-V5110-Doc/Cluster/README.md b/nodejs-V5110-Doc/Cluster/README.md index 1f3df7c..53782c9 100644 --- a/nodejs-V5110-Doc/Cluster/README.md +++ b/nodejs-V5110-Doc/Cluster/README.md @@ -37,15 +37,150 @@ # Cluster +一個運行在Nodejs的單個線程中,為了充份利用多核心系統,使用者有時候要啟動Nodejs的cluster來處理負擔 + +cluster模組允許使用者容易的去創造child processes去共享server ports + +```javascript +const cluster = require('cluster'); //引入cluster函式庫 +const http = require('http'); //引入http函式庫 +const numCPUs = require('os').cpus().length; //引入os CPU 數量 + //cluster.isMaster可以判斷目前是在主程式還是在fork出去的child process +if (cluster.isMaster) { //在主程式 + // Fork workers. // + for (var i = 0; i < (numCPUs-1); i++) { //numCPUs-1是為了讓有一顆CPU可以執行系統分配或運算 + cluster.fork(); //利用cluster.fork()產生worker + } // + // + // + cluster.on('death', function(worker) { // + console.log('worker ' + worker.pid + ' died'); // + }); // +} else { //是child process,就直接執行伺服器程式 + // Worker processes have a http server. // + http.Server(function(req, res) { // + res.writeHead(200); // + res.end("hello world\n"); //印出hello world + }).listen(8000); //port8000 +} // + +``` +執行Nodejs 127.0.0.1:8000 + +```不知到是什麼 +$ NODE_DEBUG=cluster node server.js +23521,Master Worker 23524 online +23521,Master Worker 23526 online +23521,Master Worker 23523 online +23521,Master Worker 23528 online +``` +請注意,視窗,目前還不可能建立一個名為pipe server 的工人 # How It Works +worker processes使用child_process.fork()方法所產生,以便他們可以和 parent via IPC 溝通,並透過是伺服器處理往返 +cluster模組支援分發和傳入兩個方法 +- 第一個(而在所有平台上默認除了windows),是round-robin 方法,其中master process使用port做監聽,接受新的連接並在round-robin方式下分發他們橫越每個workers,一些內建的智慧會避免worker processes超載工作 +- 第二個途徑,是master process建立一個listen socket,並將發送給有興趣的workers,然後workers直接接受傳入的連接 +第二個方法理論上應該的到最好的性能,然而再實踐上,分佈往往是非常不平衡的,由於操作系統的調度變幻莫測,負載經觀察,超過70%的連接在two processes 就結束了 + +因為server.listen()處理了大部分的master process工作,有三種情況,其中一般的Nodejs和cluster處理行為是不同的 + +- 1.server.listen({fd: 7})在master和worker溝通過程,透過傳遞文件,master會監聽"文件描述為7",而不是傳遞"文件描述為7"的引用 +- 2.server.listen(handle)master和worker溝通過程,透過handle函數進行溝通 +- 3.server.listen(0)在master和worker溝通過程,cluster中的worker會打開一個隨機窗口,透過socket通信 + +在Nodejs中沒有路由邏輯,或者在你的程式中每個workers沒有共享狀態,因此這對設計程式非常重,不會依賴太多的內存記憶體像是sessions and login + +因為每個workers在程序中式分離的,workers可以依照程式需求關閉或重起,並不會互相影響。只要有worker繼續存活,服務將繼續連接。如果全部worker被中斷,以存在的連接將被中斷,新的連接將被拒絕。Nodejs不會自動管理workers數,管理worker pool是你的管理責任 # Class: Worker +一個Worker物件包含全部的公共和方法,在master裡它可以用cluster.workers獲得,在worker裡它可以用cluster.worker獲得 ### Event: 'disconnect' +類似cluster.on('disconnect')事件,但只能在worker底下工作 +```shell +cluster.fork().on('disconnect', () => { + // Worker has disconnected +}); +``` ### Event: 'error' +這個事件和之前提過的一樣child_process.fork() +在worker也可使用process.on('error') ### Event: 'exit' +監聽worker退出事件 +- code 退出代碼,如果正常退出 +- signal 的信號名稱"SIGHUP",表示該處理被關閉 +類似cluster.on('exit')事件,但只能在worker底下工作 +```shell +const worker = cluster.fork(); +worker.on('exit', (code, signal) => { + if( signal ) { + console.log(`worker was killed by signal: ${signal}`); + } else if( code !== 0 ) { + console.log(`worker exited with error code: ${code}`); + } else { + console.log('worker success!'); + } +}); +``` ### Event: 'listening' +監聽worker向master狀態事件 +- address +類似cluster.on('listening'),但只能在worker底下工作 +```shell +cluster.fork().on('listening', (address) => { + // Worker is listening +}); +``` +它不是從worker裡發出 ### Event: 'message' +- message +類似cluster.on('message'),但只能在worker底下工作 +這個事件與之前的child_process.fork()相似 +在worker裡也可使用process.on('message') +舉個例子,這裡是一個cluster,持續送出計數要求,在master處理使用系統訊息 +```shell +const cluster = require('cluster'); +const http = require('http'); + +if (cluster.isMaster) { + + // Keep track of http requests + var numReqs = 0; + setInterval(() => { + console.log('numReqs =', numReqs); + }, 1000); + + // Count requests + function messageHandler(msg) { + if (msg.cmd && msg.cmd == 'notifyRequest') { + numReqs += 1; + } + } + + // Start workers and listen for messages containing notifyRequest + const numCPUs = require('os').cpus().length; + for (var i = 0; i < numCPUs; i++) { + cluster.fork(); + } + + Object.keys(cluster.workers).forEach((id) => { + cluster.workers[id].on('message', messageHandler); + }); + +} else { + + // Worker processes have a http server. + http.Server((req, res) => { + res.writeHead(200); + res.end('hello world\n'); + + // notify master about the request + process.send({ cmd: 'notifyRequest' }); + }).listen(8000); +} +``` ### Event: 'online' +監聽worker創建成功事件 ### worker.disconnect() +中斷worker連接,讓worker消失 ### worker.exitedAfterDisconnect ### worker.id ### worker.isConnected() @@ -69,4 +204,4 @@ # cluster.settings # cluster.setupMaster([settings]) # cluster.worker -# cluster.workers \ No newline at end of file +# cluster.workers From f1d3c3c2edb49c77c87ce187195793ed45670316 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 5 May 2016 00:10:07 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nodejs-V5110-Doc/Cluster/README.md | 56 +++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/nodejs-V5110-Doc/Cluster/README.md b/nodejs-V5110-Doc/Cluster/README.md index 53782c9..1355db4 100644 --- a/nodejs-V5110-Doc/Cluster/README.md +++ b/nodejs-V5110-Doc/Cluster/README.md @@ -95,7 +95,7 @@ cluster模組支援分發和傳入兩個方法 一個Worker物件包含全部的公共和方法,在master裡它可以用cluster.workers獲得,在worker裡它可以用cluster.worker獲得 ### Event: 'disconnect' 類似cluster.on('disconnect')事件,但只能在worker底下工作 -```shell +```javascript cluster.fork().on('disconnect', () => { // Worker has disconnected }); @@ -108,7 +108,7 @@ cluster.fork().on('disconnect', () => { - code 退出代碼,如果正常退出 - signal 的信號名稱"SIGHUP",表示該處理被關閉 類似cluster.on('exit')事件,但只能在worker底下工作 -```shell +```javascript const worker = cluster.fork(); worker.on('exit', (code, signal) => { if( signal ) { @@ -124,7 +124,7 @@ worker.on('exit', (code, signal) => { 監聽worker向master狀態事件 - address 類似cluster.on('listening'),但只能在worker底下工作 -```shell +```javascript cluster.fork().on('listening', (address) => { // Worker is listening }); @@ -136,7 +136,7 @@ cluster.fork().on('listening', (address) => { 這個事件與之前的child_process.fork()相似 在worker裡也可使用process.on('message') 舉個例子,這裡是一個cluster,持續送出計數要求,在master處理使用系統訊息 -```shell +```javascript const cluster = require('cluster'); const http = require('http'); @@ -179,8 +179,56 @@ if (cluster.isMaster) { ``` ### Event: 'online' 監聽worker創建成功事件 +類似cluster.on('online'),但只能在worker底下工作 +```javascript +cluster.fork().on('online', () => { + // Worker is online +}); +``` +它不是從worker裡發出 ### worker.disconnect() 中斷worker連接,讓worker消失 +在worker裡,這個功能將會關閉所有服務,等待服務上的"close"事件,然後斷開IPC通道 +在master裡,內部訊號發送到worker,造成在自己本身呼叫.disconnect() +使得.exitedAfterDisconnect被設定 +注意,一個服務器被關閉後,它將不再接受新的連接,但連接可以由任何其他聆聽worker接受。 +現有連接照樣將被允許關閉,當沒有更多的連接存在,將看到server.close(),worker的IPC通道,將允許它關閉優雅的結束。 +以上僅適用於服務器連接,客戶端連接不會自動關閉worker,和斷開再退出之前不會等待他們關閉 +注意在一個worker裡,process.disconnect存在,但是它沒有功能,它是disconnect +因為長期工作的伺服器連接可能從disconnecting阻止worker,它可能發送一個有用的訊息,所以特定動作可用來關閉它們。 +它可以被使用在超時上,如果一段時間後disconnect事件上未發出,中斷worker +```javascript +if (cluster.isMaster) { + var worker = cluster.fork(); + var timeout; + + worker.on('listening', (address) => { + worker.send('shutdown'); + worker.disconnect(); + timeout = setTimeout(() => { + worker.kill(); + }, 2000); + }); + + worker.on('disconnect', () => { + clearTimeout(timeout); + }); + +} else if (cluster.isWorker) { + const net = require('net'); + var server = net.createServer((socket) => { + // connections never end + }); + + server.listen(8000); + + process.on('message', (msg) => { + if(msg === 'shutdown') { + // initiate graceful close of any connections to server + } + }); +} +``` ### worker.exitedAfterDisconnect ### worker.id ### worker.isConnected() From b5ba4489399bdbb0502460b0b42d1a96e4e9ab7f Mon Sep 17 00:00:00 2001 From: user Date: Thu, 5 May 2016 00:13:50 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nodejs-V5110-Doc/Cluster/README.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/nodejs-V5110-Doc/Cluster/README.md b/nodejs-V5110-Doc/Cluster/README.md index 1355db4..5c7057a 100644 --- a/nodejs-V5110-Doc/Cluster/README.md +++ b/nodejs-V5110-Doc/Cluster/README.md @@ -187,16 +187,13 @@ cluster.fork().on('online', () => { ``` 它不是從worker裡發出 ### worker.disconnect() -中斷worker連接,讓worker消失 -在worker裡,這個功能將會關閉所有服務,等待服務上的"close"事件,然後斷開IPC通道 -在master裡,內部訊號發送到worker,造成在自己本身呼叫.disconnect() -使得.exitedAfterDisconnect被設定 -注意,一個服務器被關閉後,它將不再接受新的連接,但連接可以由任何其他聆聽worker接受。 -現有連接照樣將被允許關閉,當沒有更多的連接存在,將看到server.close(),worker的IPC通道,將允許它關閉優雅的結束。 -以上僅適用於服務器連接,客戶端連接不會自動關閉worker,和斷開再退出之前不會等待他們關閉 -注意在一個worker裡,process.disconnect存在,但是它沒有功能,它是disconnect -因為長期工作的伺服器連接可能從disconnecting阻止worker,它可能發送一個有用的訊息,所以特定動作可用來關閉它們。 -它可以被使用在超時上,如果一段時間後disconnect事件上未發出,中斷worker +- 中斷worker連接,讓worker消失 +- 在worker裡,這個功能將會關閉所有服務,等待服務上的"close"事件,然後斷開IPC通道 +- 在master裡,內部訊號發送到worker,造成在自己本身呼叫.disconnect()使得.exitedAfterDisconnect被設定 +- 注意,一個服務器被關閉後,它將不再接受新的連接,但連接可以由任何其他聆聽worker接受。 +- 現有連接照樣將被允許關閉,當沒有更多的連接存在,將看到server.close(),worker的IPC通道,將允許它關閉優雅的結束。 +- 以上僅適用於服務器連接,客戶端連接不會自動關閉worker,和斷開再退出之前不會等待他們關閉 +- 注意在一個worker裡,process.disconnect存在,但是它沒有功能,它是disconnect,因為長期工作的伺服器連接可能從disconnecting阻止worker,它可能發送一個有用的訊息,所以特定動作可用來關閉它們。它可以被使用在超時上,如果一段時間後disconnect事件上未發出,中斷worker ```javascript if (cluster.isMaster) { var worker = cluster.fork(); From 95371900dcf3f5893bf61f5cad40730e09239de1 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 5 May 2016 00:41:48 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nodejs-V5110-Doc/Cluster/README.md | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/nodejs-V5110-Doc/Cluster/README.md b/nodejs-V5110-Doc/Cluster/README.md index 5c7057a..4e376ce 100644 --- a/nodejs-V5110-Doc/Cluster/README.md +++ b/nodejs-V5110-Doc/Cluster/README.md @@ -235,8 +235,41 @@ if (cluster.isMaster) { ### worker.send(message[, sendHandle][, callback]) ### worker.suicide # Event: 'disconnect' +- worker {Worker object} # Event: 'exit' +- worker +- code 退出代碼,如果正常退出 +- signal 的信號名稱"SIGHUP",表示該處理被關閉 +當有任何workers被結束時,cluster模組會發送"exit"事件 +透過再次使用fork()函數,可以使用這個事件來重起worker +```javascript +cluster.on('exit', (worker, code, signal) => { + console.log('worker %d died (%s). restarting...', + worker.process.pid, signal || code); + cluster.fork(); +}); +``` +看child_process event: 'exit' # Event: 'fork' +- worker +當一個新的worker被分支出來,cluster模組會產生一個"fork"事件。這被用來紀錄worker進行過的活動,以及建立你自己的超時判斷 +```javascript +var timeouts = []; +function errorMsg() { + console.error('Something must be wrong with the connection ...'); +} + +cluster.on('fork', (worker) => { + timeouts[worker.id] = setTimeout(errorMsg, 2000); +}); +cluster.on('listening', (worker, address) => { + clearTimeout(timeouts[worker.id]); +}); +cluster.on('exit', (worker, code, signal) => { + clearTimeout(timeouts[worker.id]); + errorMsg(); +}); +``` # Event: 'listening' # Event: 'message' # Event: 'online'