分享一个将pomelo config解析为pm2 config的脚本

原文发表在我的个人博客http://kikoroc.com/2016/06/15/parse-pomelo-server-config-to-pm2-config.html

pomelo原生自带的pomelo start等命令可以很好的在开发过程中使用,但是到产品部署阶段就显得有些力不从心。在pomelo集群部署方面,推荐使用pm2来运维部署pomelo服务器组。用过才知道真的比pomelo start等命令爽快很多,墙裂推荐。

本文主要分享一个将pomelo config解析为pm2 config的脚本。

parse_pomelo_to_pm2_config.js

/**
 * 将pomelo默认配置servers.json转为pm2配置
 * Created by kikoroc on 16/4/26.
 */
var env = 'production';
var servers = require('../servers.json')[env];
var master = require('../master.json')[env];
var masterha = require('../masterha.json').masterha;
var fs = require('fs');

/**
 * 一台服务器可能有多个网络类型的ip地址(电信移动联通局域网等),这里主要配置将服务器多个ip解析为同一个ip
 * 这样就可以将同服务器的pomelo config配置到一个pm2 config json文件中。
 */
var _SERVER_IPMAP = {
    "your_server_telecom_ip": "your_server_telecom_ip",
    "mobile_ip": "your_server_telecom_ip",
    "unicom_ip": "your_server_telecom_ip",
    "local_ip": "your_server_telecom_ip"
};

var _RESULT = {};

for(var serverType in servers){
    servers[serverType].forEach(function(conf){
        var process = {
            "name": "",
            "cwd": "/data/xxx/game-server/",
            "script": "app.js",
            "args": null,
            "exec_mode": "fork",
            "watch": false,
            "env": {
                "NODE_ENV": "production"
            },
            "merge_logs": true,
            "error_file": "",
            "out_file": "",
            "autorestart": true,
            "max_memory_restart": "1G"
        };
        process.name = conf.id;
        process.error_file = "/data/xxx/game-server/logs/"+conf.id+"_error.log";
        process.out_file = "/data/xxx/game-server/logs/"+conf.id+"_normal.log";
        var args = [];
        args.push("env=production");
        args.push("serverType="+serverType);
        for(var k in conf){
            args.push(k+"="+conf[k]);
        }
        process.args = args;

        var destHost = _SERVER_IPMAP[conf.host];
        if(_RESULT.hasOwnProperty(destHost)){
            _RESULT[destHost].apps.push(process);
        }else{
            _RESULT[destHost] = {};
            _RESULT[destHost]['apps'] = [];
            _RESULT[destHost].apps.push(process);
        }
    });
}

masterha.forEach(function(conf){
    fs.writeFileSync('./out/masterha@'+_SERVER_IPMAP[conf.host]+'.json', JSON.stringify({
        "apps": [{
            "name": conf.id,
            "cwd": "/data/xxx/game-server/",
            "script": "app.js",
            "args": [
                "serverType=master",
                "id="+conf.id,
                "host="+conf.host,
                "port="+conf.port,
                "env=production",
                "mode=stand-alone",
                "masterha=true"
            ],
            "exec_mode": "fork",
            "watch": false,
            "env": {
                "NODE_ENV":"production"
            },
            "merge_logs": true,
            "error_file": "/data/xxx/game-server/logs/"+conf.id+"_error.log",
            "out_file": "/data/xxx/game-server/logs/"+conf.id+"_normal.log",
            "autorestart": true,
            "max_memory_restart": "1G"
        }]
    }, null, 2), {
        flag: 'w'
    });
});

//write master config
fs.writeFileSync('./out/master@'+_SERVER_IPMAP[master.host]+'.json', JSON.stringify({
    "apps": [{
        "name": master.id,
        "cwd": "/data/xxx/game-server/",
        "script": "app.js",
        "args": [
            "serverType=master",
            "id="+master.id,
            "host="+master.host,
            "port="+master.port,
            "env=production",
            "mode=stand-alone"
        ],
        "exec_mode": "fork",
        "watch": false,
        "env": {
            "NODE_ENV":"production"
        },
        "merge_logs": true,
        "error_file": "/data/xxx/game-server/logs/"+master.id+"_error.log",
        "out_file": "/data/xxx/game-server/logs/"+master.id+"_normal.log",
        "autorestart": true,
        "max_memory_restart": "1G"
    }]
}, null, 2), {
    flag: 'w'
});

for(var host in _RESULT){
    fs.writeFileSync('./out/'+host+'.json', JSON.stringify(_RESULT[host], null, 2), {
        flag: 'w'
    });
}

运行

node parse_pomelo_to_pm2_config.js

pm2的json config文件就会生成在./out/目录下。然后分发到对应的服务器执行pm2 start xxx.json即可。

在实际运维过程中,可能需要重启某些serverType的服务器进程,这里再分享一个根据serverType生成对应服务器进程重启的脚本。

gen_restart_shell_by_serverType.js

/**
 * 生成重启业务服务进程的pm2代码
 * Created by kikoroc on 16/4/27.
 */
var serverType = 'chat';
var servers = require('../../servers.json')['production'][serverType];

if(servers && servers.length > 0){
    servers.forEach(function(svr){
        console.log('ssh '+svr.host+' /usr/local/bin/pm2 restart '+svr.id);
    });
}else{
    console.error('no server of '+serverType);
}

运行

node gen_restart_shell_by_serverType.js > restart_chat.sh
bash restart_chat.sh

即可完成chat servers的重启。:)

标签: pomelo
kikoroc 在 2016-6-15 17:23发布 分享到 weibo
3 回复
#1 kikoroc 2016-6-15 17:25 回复

额,对markdown代码解析不太友好~ 需要的话可以去我博客看代码。

#2 {2} reerayxia 2016-6-21 12:43 回复

看了下代码,明白了意思
虽然我不懂PM2
不过,楼主的代码中var env = 'production';
没用到,可以改进下

另外,上述代码貌似针对pomelo2之前的版本

kikoroc 2016-6-21 15:07 回复

var env = 'production';
是指定解析servers.json中对应环境的配置。
我这里偷懒直接写死了,也可以通过var env = process.NODE_ENV || 'production';在执行时指定。

请教下你们在生成环境中用上pomelo2了吗?

reerayxia 2016-6-21 15:15 回复

@kikoroc 前阵子电脑升级,全新安装的,就直接用pomelo2。感觉就是启动机制变了

#3 innocentjulie 11-7 20:02 回复

masterha.json是啥,我怎么没有这个文件

回到顶部