<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## 概述 ### 基本用法 Node.js默認單進程運行,對于多核CPU的計算機來說,這樣做效率很低,因為只有一個核在運行,其他核都在閑置。cluster模塊就是為了解決這個問題而提出的。 cluster模塊允許設立一個主進程和若干個worker進程,由主進程監控和協調worker進程的運行。worker之間采用進程建通信交換消息,cluster模塊內置一個負載均衡器,采用Round-robin算法協調各個worker進程之間的負載。運行時,所有新建立的鏈接都由主進程完成,然后主進程再把TCP連接分配給指定的worker進程。 ~~~ var cluster = require('cluster'); var os = require('os'); if (cluster.isMaster){ for (var i = 0, n = os.cpus().length; i < n; i += 1){ cluster.fork(); } } else { http.createServer(function(req, res) { res.writeHead(200); res.end("hello world\n"); }).listen(8000); } ~~~ 上面代碼先判斷當前進程是否為主進程(cluster.isMaster),如果是的,就按照CPU的核數,新建若干個worker進程;如果不是,說明當前進程是worker進程,則在該進程啟動一個服務器程序。 ### cluster.worker對象 cluster.worker指向當前worker進程對象,主進程沒有這個值。 它有如下屬性。 (1)worker.id work.id返回當前worker的獨一無二的進程編號。這個編號也是cluster.workers中指向當前進程的索引值。 (2)worker.process 所有的worker進程都是用child_process.fork()生成的。child_process.fork()返回的對象,就被保存在worker.process之中。通過這個屬性,可以獲取worker所在的進程對象。 (3)worker.send() 該方法用于在主進程中,向子進程發送信息。 ~~~ if (cluster.isMaster) { var worker = cluster.fork(); worker.send('hi there'); } else if (cluster.isWorker) { process.on('message', function(msg) { process.send(msg); }); } ~~~ 上面代碼的作用是,worker進程對主進程發出的每個消息,都做回聲。 在worker進程中調用這個方法,等同于process.send(message)。 ### cluster.workers對象 該對象只有主進程才有,包含了所有worker進程。每個成員的鍵值就是一個worker進程,鍵名就是該worker進程的worker.id屬性。 ~~~ function eachWorker(callback) { for (var id in cluster.workers) { callback(cluster.workers[id]); } } eachWorker(function(worker) { worker.send('big announcement to all workers'); }); ~~~ 上面代碼用來遍歷所有worker進程。 當前socket的data事件,也可以用id屬性識別worker進程。 ~~~ socket.on('data', function(id) { var worker = cluster.workers[id]; }); ~~~ ## 屬性與方法 ### isMaster,isWorker isMaster屬性返回一個布爾值,表示當前進程是否為主進程。這個屬性由process.env.NODE_UNIQUE_ID決定,如果process.env.NODE_UNIQUE_ID為未定義,就表示該進程是主進程。 isWorker屬性返回一個布爾值,表示當前進程是否為work進程。它與isMaster屬性的值正好相反。 ### fork() fork方法用于新建一個worker進程,上下文都復制主進程。只有主進程才能調用這個方法。 該方法返回一個worker對象。 ### kill() kill方法用于終止worker進程。它可以接受一個參數,表示系統信號。 如果當前是主進程,就會終止與worker.process的聯絡,然后將系統信號法發向worker進程。如果當前是worker進程,就會終止與主進程的通信,然后退出,返回0。 在以前的版本中,該方法也叫做 worker.destroy() 。 ### listening事件 worker進程調用listen方面以后,“listening”就傳向該進程的服務器,然后傳向主進程。 該事件的回調函數接受兩個參數,一個是當前worker對象,另一個是地址對象,包含網址、端口、地址類型(IPv4、IPv6、Unix socket、UDP)等信息。這對于那些服務多個網址的Node應用程序非常有用。 ~~~ cluster.on('listening', function(worker, address) { console.log("A worker is now connected to " + address.address + ":" + address.port); }); ~~~ ## 實例:不中斷地重啟Node服務 重啟服務需要關閉后再啟動,利用cluster模塊,可以做到先啟動一個worker進程,再把原有的所有work進程關閉。這樣就能實現不中斷地重啟Node服務。 下面是主進程的代碼master.js。 ~~~ var cluster = require('cluster'); console.log('started master with ' + process.pid); // 新建一個worker進程 cluster.fork(); process.on('SIGHUP', function () { console.log('Reloading...'); var new_worker = cluster.fork(); new_worker.once('listening', function () { // 關閉所有其他worker進程 for(var id in cluster.workers) { if (id === new_worker.id.toString()) continue; cluster.workers[id].kill('SIGTERM'); } }); }); ~~~ 上面代碼中,主進程監聽SIGHUP事件,如果發生該事件就關閉其他所有worker進程。之所以是SIGHUP事件,是因為nginx服務器監聽到這個信號,會創造一個新的worker進程,重新加載配置文件。另外,關閉worker進程時,主進程發送SIGTERM信號,這是因為Node允許多個worker進程監聽同一個端口。 下面是worker進程的代碼server.js。 ~~~ var cluster = require('cluster'); if (cluster.isMaster) { require('./master'); return; } var express = require('express'); var http = require('http'); var app = express(); app.get('/', function (req, res) { res.send('ha fsdgfds gfds gfd!'); }); http.createServer(app).listen(8080, function () { console.log('http://localhost:8080'); }); ~~~ 使用時代碼如下。 ~~~ $ node server.js started master with 10538 http://localhost:8080 ~~~ 然后,向主進程連續發出兩次SIGHUP信號。 ~~~ $ kill -SIGHUP 10538 $ kill -SIGHUP 10538 ~~~ 主進程會連續兩次新建一個worker進程,然后關閉所有其他worker進程,顯示如下。 ~~~ Reloading... http://localhost:8080 Reloading... http://localhost:8080 ~~~ 最后,向主進程發出SIGTERM信號,關閉主進程。 ~~~ $ kill 10538 ~~~ ## PM2模塊 PM2模塊是cluster模塊的一個包裝層。它的作用是盡量將cluster模塊抽象掉,讓用戶像使用單進程一樣,部署多進程Node應用。 ~~~ // app.js var http = require('http'); http.createServer(function(req, res) { res.writeHead(200); res.end("hello world"); }).listen(8080); ~~~ 上面代碼是標準的Node架設Web服務器的方式,然后用PM2從命令行啟動這段代碼。 ~~~ $ pm2 start app.js -i 4 ~~~ 上面代碼的i參數告訴PM2,這段代碼應該在cluster_mode啟動,且新建worker進程的數量是4個。如果i參數的值是0,那么當前機器有幾個CPU內核,PM2就會啟動幾個worker進程。 如果一個worker進程由于某種原因掛掉了,會立刻重啟該worker進程。 ~~~ # 重啟所有worker進程 $ pm2 reload all ~~~ 每個worker進程都有一個id,可以用下面的命令查看單個worker進程的詳情。 ~~~ $ pm2 show <worker id> ~~~ 正確情況下,PM2采用fork模式新建worker進程,即主進程fork自身,產生一個worker進程。`pm2 reload`命令則會用spawn方式啟動,即一個接一個啟動worker進程,一個新的worker啟動成功,再殺死一個舊的worker進程。采用這種方式,重新部署新版本時,服務器就不會中斷服務。 ~~~ $ pm2 reload <腳本文件名> ~~~ 關閉worker進程的時候,可以部署下面的代碼,讓worker進程監聽shutdown消息。一旦收到這個消息,進行完畢收尾清理工作再關閉。 ~~~ process.on('message', function(msg) { if (msg === 'shutdown') { close_all_connections(); delete_logs(); server.close(); process.exit(0); } }); ~~~ ## 參考鏈接 * José F. Romaniello,?[Reloading node with no downtime](http://joseoncode.com/2015/01/18/reloading-node-with-no-downtime/) * Joni Shkurti,?[Node.js clustering made easy with PM2](https://keymetrics.io/2015/03/26/pm2-clustering-made-easy/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看