Node.js站群管理系统的实现之增加多服务器节点支持、进程重启、npm包安装、实时日志查看

 2015年08月22日    907     声明

Node.js站群管理系统的实现之增加多服务器节点支持、进程重启、npm包安装、实时日志查看

本系统基于Socket.io和Node.js的child_process模块,Web框架使用express。上一个版本中,实现了基本的更新操作,只适用于静态HTML站点的管理。随着公司业务的增长,有两个站点做了SLB,这样站点每更新一次都要登录多台服务器,还要pull代码、重启进程。为了简化更新步骤,实现运维自动化,在这一版本,增加或优化了这些功能:实时日志查看、多服务器节点支持、进程重启、npm包安装。

  1. 项目需求
  2. 实现及关键代码说明
  3. 布署使用


在上一版本中,只要做了基于git的代码更新,核心功能是使用Node.js的child_process模块执行git pull命令更新代码。现在,随着业务量的增长,对两个Node.js的动态站做了SLB负载均衡,这就涉及多服务器代码的更新、Node进程的重启、以及可能遇到的npm包安装。

1. 项目需求

  • 1. 查看运行日志,可以方便的查看项目运行输出,并能实时查看项目的更新状态,这次增加日志查看功能
  • 2. Node.js站点进程重启,可以是基于foreverpm2shell脚本
  • 3. 项目迭代后可能会安装npm包,系统要能实现npm包安装
  • 4. SLB负载均衡后,项目维护是跨服务器多节点的,本次迭代应能满足相关需求


2. 实现及关键代码说明

2.1 站点配置

站点配置包括两部分,一是站点信息,一是服务器信息。服务器信息包括:主机IP或网址、网站文件夹、日志文件夹。站点信息包括:站点名称、站点类型、服务器节点。对于Node.js动态站点,配置还包括:日志文件名、进程重启命令。在本例中,进程重启是基于forever模块的进程重启,可根据需要自行配置,如:基于pm2的进程重启、基于shell进程重启等。配置信息位于项目根目录config.js文件中,主要配置如下:

//服务器节点配置,可以是IP或网址
servers: {
    s1: {host:'sm.itbilu.com', wwwPath: '/alidata/www/', logPath: '/root/.forever/'},
    s2: {host:'115.29.11.11:9999', wwwPath: '/home/data/', logPath: '/root/.forever/'}
},
//站点配置
sites: {
    //一个html站点配置
    ui: {
        name: '一个静态站',
	type: 'html',
	host: 's1',
	path: 'itbilu_ui'
    },
    //一个node.js动态站
    itbilu: {
	name: 'IT笔录',
 	type: 'node',
        //站点所在服务器
	host: ['s1', 's2'], 
	path: 'itbilu',
        //日志文件名
	logfile: 'itbilu.log',
	//进程重启命令,此命令最终传给child_process执行,根据需要自行配置
	restart: {cmd: 'forever', args:['restart', 'itbilu']}
    }
}


2.2 前端页面

前端页面要实现的功能有:站点信息的显示、与服务器建立socket连接、通过Soket.IO与服务器通讯、服务器执行命令后相关输出的显示。主要页面功能位于项目views/site.html文件中,页面socket相关代码如下:

//与指定的服务器节点建立soket连接
var socket = io('<%= servers[server].host %>/socket/site');
socket.on('connect', function () {
    console.log('连接成功');
    <% if( sites[key].type==='node') {%>
    //动态站,连接后显示站点日志
    var data = { cmd: 'log', site: '<%= key %>', server:'<%= server %>'};
    socket.emit('exec', data);
    <% } %>
});

//服务器站数据显示
socket.on('data', function(data){
    var log = document.getElementById('log');
    log.innerHTML = log.innerHTML +data;
    log.scrollTop=Math.max(0,log.scrollHeight-log.offsetHeight);
});

//点击按钮后,通过socket将要执行的操作传递给服务器
$('button').click(function(){
    var data = { cmd: '', site: '<%= key %>', server:'<%= server %>'};
    data.cmd = $(this).prop('name');
    socket.emit('exec', data);
});


2.3 服务器端功能

首先,项目框架使用express。服务端功能有,简单的用户登录及验证、Soket.IO服务端、客户端命令接收及转换、命令执行及执行结果回传等。服务端主要功能位与controller/site.js文件下。下面是部分功能代码:

exports.socket = function(server){
    var io = require('socket.io')(server);
    var site = io.of('/socket/site');
    //连接对象
    site.on('connection', function (socket) {		
	socket.on('exec', function(data){
	    var arg = _makeCmd(data);
	    var child = child_process.spawn(arg.cmd, arg.args, {cwd:arg.cwd});
	    //打印子进程的输出数据
	    child.stdout.on('data', function (data) {
		// console.log(data);
		socket.emit('data', data.toString());
	    });

	    //监听子进程的错误流数据
	    child.stderr.on('data', function (data) {
		console.log('stderr: ' + data.toString());
	        socket.emit('err', data.toString());
	    });

	    //监听子进程的退出事件
	    child.on('close', function (code) {
		console.log('子进程退出,code:' + code);
	        socket.emit('err', '子进程退出,code:' + code);
		});
	});

	//连接断开处理
	socket.on('disconnect', function (){
	    	
	});
    });
}

//构建命令
function _makeCmd(data){
    var sites = config.sites;
    var  servers = config.servers;
    var cmd = '';
    var args = [];
    var cwd = '';
    switch(data.cmd){
	case 'pull':
  	    cmd = 'git';
	    args = ['pull'];
	    cwd =  servers[data.server].wwwPath + sites[data.site].path;
	    break;
	case 'restart':
	    cmd = sites[data.site].restart.cmd;
	    args = sites[data.site].restart.args;
	    cwd =  servers[data.server].wwwPath + sites[data.site].path;
	    break;
	case 'npm':
	    cmd = 'npm';
	    args = ['install'];
	    cwd =  servers[data.server].wwwPath + sites[data.site].path;
	    break;
	case 'log':
	    cmd = 'tail';
	    args = ['-f', servers[data.server].logPath + sites[data.site].logfile];
	    cwd =  '/';
	   break;
    }

    return {
	cmd: cmd,
	args: args,
	cwd: cwd
    }
}


3. 布署使用

3.1 配置

配置文件,即:项目根目录的config.js文件,需要配置serverssites两个节点。


3.2 安装

配置完成后,要在所有servers节点配置的服务器下载本系统。下载后,在项目根目录执行npm install命令安装项目依赖包,安装完成启动项目。


3.3 使用

访问servers节点中任意一台服务器。登录后就可以对配置站点进行:基于git的代码更新、node进程重启、npm包安装、日志查看等。


说明:1. 系统基于git进行代码管理,应确保配置站点有访问git服务器的权限,即:已配置git SSH。2. 对SLB负载均衡的站点,应在每个服务器节点都安装配置本系统,每个系统节点都需要单独更新及进程重启等。

项目github地址:node-site-manager