pomelo服務(wù)器部署問(wèn)題
pemelo可以使用 'pomelo start -e production' 命令在服務(wù)器運(yùn)行生產(chǎn)環(huán)境的服務(wù)器代碼盼铁。pomelo自身缺少進(jìn)程監(jiān)控储藐,運(yùn)行過(guò)程中不方便獲取到進(jìn)程的運(yùn)行信息有送。而且pomelo沒(méi)有進(jìn)程保護(hù)控汉,當(dāng)進(jìn)程崩潰之后,不能自動(dòng)重啟進(jìn)程。pomelo提供的單服務(wù)器重啟動(dòng)功能不能使用授翻,至少目前的2.2.5版本中不能使用單個(gè)服務(wù)器重啟功能。當(dāng)完成某個(gè)服務(wù)器的代碼的修改之后孙咪,只能把全部服務(wù)器關(guān)掉堪唐,之后再全部啟動(dòng)一次。只修改后端服務(wù)器的代碼该贾,要讓代碼生效只能全部重啟一次羔杨,會(huì)導(dǎo)致全部玩家斷線重新連接。如果只是單獨(dú)重啟一個(gè)后端服務(wù)器杨蛋,則不會(huì)出現(xiàn)全部客戶(hù)端斷線重連的問(wèn)題兜材。
pm2配置文件
使用PM2部署項(xiàng)目,需要一份部署配置文件逞力,用于描述pomelo服務(wù)器的進(jìn)程信息曙寡。pomelo的進(jìn)程主要包括master進(jìn)程和各個(gè)功能服務(wù)器。
master進(jìn)程的配置,配置文件需要指定 log文件的目錄寇荧,項(xiàng)目代碼的目錄举庶。還有重要的一點(diǎn)是要指定進(jìn)程的模式mode=stand-alone,如果不指定master進(jìn)程的模式,導(dǎo)致pomelo多次啟動(dòng)服務(wù)器進(jìn)程揩抡,然后會(huì)看到系統(tǒng)里有不少重復(fù)進(jìn)程户侥。
{
"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"
}
其他功能服務(wù)器,需要配置各自的端口號(hào)碼和host地址峦嗤。具體的配置信息根據(jù)server.json的配置來(lái)蕊唐。
{
"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配置文件
當(dāng)需要修改項(xiàng)目中master.json或者server.json文件時(shí),需要同步去修改 pm2的配置問(wèn)題烁设,會(huì)相當(dāng)麻煩替梨。于是寫(xiě)了一個(gè)node.js腳本,讀取master.json 和 server.json的文件內(nèi)容生成對(duì)應(yīng)的PM2配置文件generatePm2Config.js装黑。 根據(jù)實(shí)際情況修改變量cwd,envType, 生成的配置文件放到腳本的父目錄副瀑。
/**
* Created by superzhan on 2018/3/19.
*
* 根據(jù)pomelo 的 servers.json 生成 pm2 啟動(dòng)文件
*/
var masterJsonFile = require('../game-server/config/master.json');
var serversJosnFile = require('../game-server/config/servers.json');
//pomelo 源碼目錄
var cwd='/root/pomelo/PirateClashPomeloServer/game-server';
//配置運(yùn)行環(huán)境 development production
var envType= 'production';
//模板數(shù)據(jù)
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",
};
//最后的結(jié)果數(shù)據(jù)
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);
//生成當(dāng)個(gè)服務(wù)器的配置
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);
}
}
//生成結(jié)果數(shù)據(jù)
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管理
啟動(dòng)服務(wù)器使用命令 pm2 start pomeloPm2Start.json
,pomeloPm2Start.json是上面生成的配置文件。
監(jiān)控命令 pm2 monit
查看各個(gè)進(jìn)程的運(yùn)行狀態(tài)恋谭, pm2 log
輸出工程的log, pm2 list
列出所有的服務(wù)器進(jìn)程
單個(gè)服務(wù)器的重啟 pm2 restart processId
, processId 對(duì)應(yīng)服務(wù)器進(jìn)程的Id.