關於node.js的進程管理

若是是單純的運行一個node進程,那會比較簡單,例如:html

node ./example.js

可是通常來講,當咱們運行一個node進程以後,咱們可能但願對這個進程進行更多的管理,例如,當node程序是一個server服務時,咱們就有更多的需求。node

例如:git

1.服務掛掉的時候自動重啓。github

2.列出全部服務,包括服務的信息。併發

3.可以重啓/終止某個服務。dom

4.爲服務的運行記錄日誌。socket

 

1.服務掛掉的時候自動重啓。ui

對於這個需求,咱們須要作的是把服務進程當作一個子進程來運行,當子進程不幸掛了,父進程將其重啓,例如:this

var spawn = require('child_process').spawn;
var cp = spawn(process.execPath,['./example.js']);

cp.on('exit',function(){
    //restart
});

假設父進程程序名爲pro_a,那麼經過父進程啓動一個子程序會是這樣:spa

pro_a ./example.js

傳入子程序名,由父程序執行。

 

這樣至關於pro_a程序管理子程序的執行:

 

2.列出全部服務,包括服務的信息。

假設咱們執行example.js以後,還有多個程序須要執行,每一個程序都使用pro_a程序來啓動:

pro_a ./example.js
pro_a ./server.js
pro_a ./other.js

 

狀況變成這樣:

 

 

如上圖,多個pro_a進程對應開啓的多個不一樣子程序的進程。

這時候問題來了,咱們但願知道全部用pro_a啓動的子進程的進程信息,要怎麼作呢?

例如:

pro_a -l //列出全部子進程信息

 

這時候需求就轉變成:新的pro_a進程須要和其餘pro_a進程通訊,並獲取其餘pro_a進程運行的子進程的信息。

 

對於UNIX的跨進程通訊,有幾種方式,因爲這裏不一樣進程在同一個機器中,所以咱們這裏採用UNIX domain socket的方式(不用通過網卡),讓在不一樣pro_a進程間進行通訊。

使用這種方式,咱們須要作的是pro_a進程每次建立子進程的時候,啓用一個server,並監聽對應的sock文件,那麼小心的pro_a進程啓動以後,就能夠經過遍歷全部sock文件並對有效sock文件進行鏈接,從而可以和不一樣pro_a進程之間進行消息的通訊。

 

例如:

建立子進程的pro_a:

var net = require('net');    
//使用UNIX domain socket
var server = net.createServer(function(socket){    
    socket.setEncoding('UTF8');
    socket.on('data',function(){
        //收到消息後,向請求方發送子進程相關信息
        socket.write(JSON.stringify({
            pid:child_process.pid
            //...
        }));
    });

});

server.listen(socketPath + 'resume_' + Date.now() + '.sock');       

 

這樣每一個pro_a進程建立子進程以後,都會對應產生一個sock文件:

 

 

對於新的pro_a進程,第一步是獲取全部sock文件,並進行鏈接:

var getAllSocketFiles = function(){
    var socketFiles;
    try{
        socketFiles = fs.readdirSync(socketPath);
    }
    catch(ex){
        if(ex.code == 'ENOENT'){
            fs.mkdirSync(socketPath);
        }

        socketFiles = fs.readdirSync(socketPath);
    }
    return socketFiles;
};

 

針對每一個sock文件,建立socket進行鏈接,併發送消息請求:

var socket = new net.Socket();
socket.setEncoding('UTF8');

socket.connect(this.socketName,function(){
    socket.write(JSON.stringify({
        //請求對應的子進程信息
    }))
});

socket.on('data',function(){
    data = JSON.parse(data);
    //得到對應子進程信息
});

 

 

這樣pro_a進程就能從其餘pro_進程中獲取到信息。

 

3.可以重啓/終止某個服務。

因爲咱們設置了子程序在掛掉後會自動重啓,所以咱們須要增長一個命令讓程序在須要時能正常關閉,例如:

pro_a -s 1140 //強制終止掉進程號爲1140的子進程

 

此時該pro_a進程須要鏈接全部其餘pro_a進程並獲取他們的子進程信息(就像上面-l那樣),而後篩選出pid未1140的子進程,再次經過socket發送關閉指令,對應的server接收到關閉指令後把其子進程kill掉。

 

4.爲服務的運行記錄日誌。

這個只須要pro_a監聽子進程的事件,並實時寫入log文件就ok了。而且咱們能夠經過命令讓心的pro_a進程可以查看某個其餘pro_a進程中子進程的log,例如:

pro_a -L 1130 // 查看1130的子進程的log

 

原理和3類似,獲取全部pro_a進程信息,篩選出pid爲1130的子進程,socket發送獲取log的指令,對應server把log信息返回。

 

我把以上pro_a的功能以及更多其餘功能封裝成一個叫Resume.js的程序放倒github上,有興趣的同窗能夠看看:

https://github.com/csonlai/Resume.js

 

其中包含了上面功能的實現源碼。咱們能夠經過Resume.js進行簡單的node進程管理。

 

歡迎圍觀,轉載請標明出處:

http://www.cnblogs.com/Cson/p/4069868.html 

相關文章
相關標籤/搜索