使用PM2部署pomelo服务器

pomelo服务器部署问题

pemelo可以使用 'pomelo start -e production' 命令在服务器运行生产环境的服务器代码。pomelo自身缺少进程监控,运行过程中不方便获取到进程的运行信息。而且pomelo没有进程保护,当进程崩溃之后,不能自动重启进程。pomelo提供的单服务器重启动功能不能使用,至少目前的2.2.5版本中不能使用单个服务器重启功能。当完成某个服务器的代码的修改之后,只能把全部服务器关掉,之后再全部启动一次。只修改后端服务器的代码,要让代码生效只能全部重启一次,会导致全部玩家断线重新连接。如果只是单独重启一个后端服务器,则不会出现全部客户端断线重连的问题。

pm2配置文件

使用PM2部署项目,需要一份部署配置文件,用于描述pomelo服务器的进程信息。pomelo的进程主要包括master进程和各个功能服务器。

master进程的配置,配置文件需要指定 log文件的目录,项目代码的目录。还有重要的一点是要指定进程的模式mode=stand-alone,如果不指定master进程的模式,导致pomelo多次启动服务器进程,然后会看到系统里有不少重复进程。

{
  "name": "master",
  "script": "app.js",
  "args": [
    "serverType=master",
    "id=master-server-1",
    "host=47.100.96.55",
    "port=4060",
    "env=production",
    "mode=stand-alone"
  ],
  "watch": false,
  "out_file": "./logs/master-server-1_app.log",
  "error_file": "./logsmaster-server-1_error.log",
  "cwd": "/root/pomelo/PirateClashPomeloServer/game-server",
  "merge_logs": true,
  "exec_mode": "fork_mode"
}

其他功能服务器,需要配置各自的端口号码和host地址。具体的配置信息根据server.json的配置来。


{
  "name": "gamehttp",
  "script": "app.js",
  "args": [
    "env=production",
    "id=gamehttp",
    "port=4050",
    "host=127.0.0.1",
    "serverType=gamehttp"
  ],
  "watch": false,
  "out_file": "./logs/gamehttp_app.log",
  "error_file": "./logs/gamehttp_error.log",
  "cwd": "/root/pomelo/PirateClashPomeloServer/game-server",
  "merge_logs": true,
  "exec_mode": "fork_mode"
}
 

使用脚本生成PM2配置文件

当需要修改项目中master.json或者server.json文件时,需要同步去修改 pm2的配置问题,会相当麻烦。于是写了一个node.js脚本,读取master.json 和 server.json的文件内容生成对应的PM2配置文件generatePm2Config.js。 根据实际情况修改变量cwd,envType, 生成的配置文件放到脚本的父目录。


/**
 * Created by superzhan on 2018/3/19.
 *
 * 根据pomelo 的 servers.json 生成 pm2 启动文件
 */

var masterJsonFile = require('../game-server/config/master.json');
var serversJosnFile = require('../game-server/config/servers.json');

//pomelo 源码目录
var cwd='/root/pomelo/PirateClashPomeloServer/game-server';

//配置运行环境 development production
var envType= 'production';

//模板数据
var processConfigType =   {
    "name"        : "",
    "script"      : "app.js",
    "args"        :  [] ,
    "watch": false,
    "out_file": "./logs/app.log",
    "error_file": "./logs/err.log",
    "cwd": "",
    "merge_logs": true,
    "exec_mode": "fork_mode",
};


//最后的结果数据
var resultJson={};
resultJson.apps=new Array();


var  clone = function(origin) {
    if(!origin) {
        return;
    }
    var obj = {};
    for(var f in origin) {
        obj[f] = origin[f];
    }
    return obj;
};

//
var masterConfig = masterJsonFile[envType];
var serversConfig = serversJosnFile[envType];

//生成master 的配置
var pm2Master = clone( processConfigType );
pm2Master.name="master";
pm2Master.args = new Array();
pm2Master.args.push('serverType=master');
pm2Master.args.push('id='+masterConfig.id);
pm2Master.args.push('host='+masterConfig.host);
pm2Master.args.push('port='+masterConfig.port);
pm2Master.args.push('env='+envType);
pm2Master.args.push('mode=stand-alone');
pm2Master.cwd= cwd;
pm2Master.out_file = './logs/'+masterConfig.id+"_app.log";
pm2Master.error_file='./logs'+masterConfig.id+'_error.log';
resultJson.apps.push(pm2Master);

//生成当个服务器的配置
for(serverType in serversConfig)
{
    var servers = serversConfig[serverType];
    for(var i=0;i<servers.length;++i)
    {
        var singleServer= servers[i];

        var appPm2Config =  clone(processConfigType);
        appPm2Config.name=singleServer.id;
        appPm2Config.args= new Array();
        appPm2Config.args.push('env='+envType);
        appPm2Config.args.push('id='+singleServer.id);
        appPm2Config.args.push('port='+singleServer.port);
        appPm2Config.args.push('host='+singleServer.host);
        appPm2Config.args.push('serverType='+serverType);

        if(singleServer.frontend !=null)
        {
            appPm2Config.args.push('frontend='+ singleServer.frontend);
            appPm2Config.args.push('clientPort='+singleServer.clientPort);
        }

        appPm2Config.cwd= cwd;
        appPm2Config.out_file = './logs/'+ singleServer.id+'_app.log';
        appPm2Config.error_file = './logs/'+singleServer.id+'_error.log';

        resultJson.apps.push(appPm2Config);
    }
}



//生成结果数据
var resultFileStr = JSON.stringify(resultJson);
//console.log(resultFileStr);


var fs = require('fs');

fs.writeFile('../pomeloPm2Start.json', resultFileStr, function (err) {
    if (err) {
        console.log(err);
    } else {
        console.log('finish genereate Server pm2 config');
    }
});

PM2管理

启动服务器使用命令 pm2 start pomeloPm2Start.json,pomeloPm2Start.json是上面生成的配置文件。

监控命令 pm2 monit 查看各个进程的运行状态, pm2 log 输出工程的log, pm2 list 列出所有的服务器进程

单个服务器的重启 pm2 restart processId, processId 对应服务器进程的Id.

发表评论

电子邮件地址不会被公开。 必填项已用*标注