關於node.js的程式管理

Cson發表於2014-11-02

如果是單純的執行一個node程式,那會比較簡單,例如:

node ./example.js

但是一般來說,當我們執行一個node程式之後,我們可能希望對這個程式進行更多的管理,例如,當node程式是一個server服務時,我們就有更多的需求。

例如:

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

2.列出所有服務,包括服務的資訊。

3.能夠重啟/終止某個服務。

4.為服務的執行記錄日誌。

 

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

對於這個需求,我們需要做的是把服務程式當做一個子程式來執行,當子程式不幸掛了,父程式將其重啟,例如:

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

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

假設父程式程式名為pro_a,那麼通過父程式啟動一個子程式會是這樣:

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 

相關文章