使用cluster模塊啟動(dòng)多進(jìn)程nodejs應(yīng)用

使用命令行的方式運(yùn)行nodejs web應(yīng)用,一旦程序有bug造成進(jìn)程崩潰,應(yīng)用就不能繼續(xù)提供服務(wù)了;并且,nodejs是單線程的模式,不能充分利用服務(wù)器的多核資源。使用node的cluster模塊可以監(jiān)控應(yīng)用進(jìn)程,退出后重新啟動(dòng)node應(yīng)用進(jìn)程,并可以啟動(dòng)多個(gè)node應(yīng)用進(jìn)程,做到負(fù)載均衡,充分利用資源。

啟動(dòng)單個(gè)進(jìn)程

node bin/www

文件www的內(nèi)容為:


/**
 * @fileOverview 應(yīng)用程序啟動(dòng)文件入口
 * @author --
 */
"use strict";

const app = require('../app');
const http = require('http');
const logger = require("../logger").appLogger();

/**
 * 設(shè)置程序監(jiān)聽(tīng)端口
 */
let port = normalizePort(config.port || process.env.PORT || '3001');
app.set('port', port);

/**
 * 創(chuàng)建http服務(wù)實(shí)例
 */
let server = http.createServer(app);

/**
 * 開(kāi)啟服務(wù)監(jiān)聽(tīng)
 */
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * 格式化監(jiān)聽(tīng)端口
 */
function normalizePort(val) {
    let port = parseInt(val, 10);

    if (isNaN(port)) {
        /** named pipe */
        return val;
    }

    if (port >= 0) {
        /** port number */
        return port;
    }

    return false;
}

/**
 * 啟動(dòng)錯(cuò)誤事件處理
 */
function onError(error) {
    if (error.syscall !== 'listen') {
        throw error;
    }

    let bind = typeof port === 'string'
            ? 'Pipe ' + port
            : 'Port ' + port;

    /** 錯(cuò)誤提示 */
    switch (error.code) {
        case 'EACCES':
            logger.error(bind + ' 權(quán)限不足');
            process.exit(1);
            break;
        case 'EADDRINUSE':
            logger.error(bind + ' 端口被占用');
            process.exit(1);
            break;
        default:
            throw error;
    }
}

/**
 * 正常啟動(dòng)事件處理
 */
function onListening() {
    let addr = server.address();
    let bind = typeof addr === 'string'
            ? 'pipe ' + addr
            : 'port ' + addr.port;
    logger.info('服務(wù)啟動(dòng)成功');
    logger.info('Listening on ' + bind);
}

cluster多進(jìn)程模式

node bin/cluster.js

文件cluster.js的內(nèi)容為:


/**
 * @fileOverview 應(yīng)用程序多進(jìn)程啟動(dòng)入口
 * @author --
 */
"use strict";

const cluster = require('cluster');
const cpus = require('os').cpus();

const accessLogger = require("../logger").accessLogger();

accessLogger.info('master ' + process.pid + ' is starting.');

cluster.setupMaster({
    /* 應(yīng)用進(jìn)程啟動(dòng)文件 */
    exec: 'bin/www'
});

/* 啟動(dòng)應(yīng)用進(jìn)程個(gè)數(shù)和服務(wù)器CPU核數(shù)一樣 */
for (let i = 0; i < cpus.length; i++) {
    cluster.fork();
}

cluster.on('online', function (worker) {
    /* 進(jìn)程啟動(dòng)成功 */
    accessLogger.info('worker ' + worker.process.pid + ' is online.');
});
cluster.on('exit', function (worker, code, signal) {
    /* 應(yīng)用進(jìn)程退出時(shí),記錄日志并重啟 */
    accessLogger.info('worker ' + worker.process.pid + ' died.');
    cluster.fork();
});

其他多進(jìn)程方案

直接使用cluster模塊管理nodejs進(jìn)程,要在生產(chǎn)環(huán)境中使用,還要做很多工作,屬于重復(fù)造輪子?,F(xiàn)在比較流行的nodejs進(jìn)程監(jiān)控和多進(jìn)程管理的工具有supervisor、forever、pm2等,下一篇將就pm2和docker談一談nodejs web應(yīng)用在生產(chǎn)環(huán)境中的部署

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容