Node.JS編程63:零停機重啟

一般情況下,當更新代碼後,必須重啟Node,才能使更新的代碼功能生效。

重啟當然是會令程序功能暫時中斷的,雖然這個過程非常短,可能只有幾秒。

普通的程序可能不需要但心這個問題,但如果是非常重要的程序,不允許間斷的程序,又該如何?

Node.JS編程63:零停機重啟
<section>
<section>
<section>

使用集群(Cluster),用“零停機重啟”方案,可以很簡單的實現這個需求。

實現代碼:

const cluster = require("cluster");

const os = require("os");

//主進程

if(cluster.isMaster){

console.log("master process id :",process.pid);

//cpu數量(幾核)

const cpus = os.cpus().length;

console.log(`Clustering to ${cpus} CPUS`);

for(let i=0; i<cpus>

//分派子進程

cluster.fork();

}

//如果工作進程關閉了,重啟一個

/*

cluster.on("exit",function(worker,code){

if(code != 0 && !worker.suicide){

console.log("worker crashed. Starting a new worker");

cluster.fork();

}

});

*/

//服務器收到這個消息

process.on("SIGINT",function(){

console.log("ctrl+c");

process.exit();

});

var express = require("express")();

express.listen(9000);

express.get("/restart",function(req,res,next){

const workers = Object.keys(cluster.workers);

//重啟函數

function restart_worker(i){

if(i >= workers.length) return;

//第i個工作進程

var worker = cluster.workers[workers[i]];

console.log(`Stoping worker:${worker.process.pid}`);

//中斷工作進程

worker.disconnect();

//工作進程退出時

worker.on("exit",function(){

/*

if(!worker.suicide){

console.log("suicide");

return;

}

*/

//啟動工作進程

const new_worker = cluster.fork();

//當新的工作進程,準備好,並開始監聽新的連接時,迭代重啟下一個工作子進程

new_worker.on("listening",function(){

restart_worker(i+1);

})

});

}

//重啟第一個工作進程

restart_worker(0);

res.end("restart ok");

});

}else{

//子進程執行內容

const http = require("http");

const pid = process.pid;

http.createServer(function(req,res){

console.log(`Handing request from ${pid}`);

res.end(`Hello from ${pid}\\n`);

}).listen(8000,function(){

console.log(`Started ${pid}`);

})

}

代碼解析:

集群主進程用express提供web服務;

集群工作進程用http提供web服務;

當主進程收到指定消息時(代碼中是訪問restart路徑),開始“零停機重啟”操作。

實現重點是:停掉一個工作進程,並重啟一個新的工作進程,當新的工作進程啟動好,並進入監聽狀態時(即:可正常提供Web服務時),再重啟下一個工作進程,直到全部重啟完成。

執行效果:


Node.JS編程63:零停機重啟
<section>
<section>
<section>

為了更真觀的展示“修改代碼,重停機重啟”效果,我們加一行代碼:

Node.JS編程63:零停機重啟
<section>
<section>
<section>

先啟動,再修改為:

Node.JS編程63:零停機重啟
<section>
<section>
<section>

再通過網頁觸發重啟:

Node.JS編程63:零停機重啟
<section>
<section>
<section>

後臺輸出同樣驗證了修改後的代碼已生效:

Node.JS編程63:零停機重啟
<section>
<section>
<section>


"/<cpus>


分享到:


相關文章: