做node层后台有一阵时间,记录一下node作为一个后台服务的部署经历的一个演进路程
常规写一个入口文件(大体是注册一些事件,然后启动一个类似ngix服务的东西)然后命令行敲node 这个入口文件名,服务也算是启动起来了~
但是呢,这种方法有个问题,就是命令行窗口不能关闭,关闭了,服务就挂了,开发什么的无所谓,测试生产的服务器是不可能做到这一点的,所以想了个法子,让服务后台运行,这就又进一步了,写了个脚本文件server.sh,大体是这样。
APP_HOME=$(echo `pwd` | sed 's/\/bin//')
SERVER_PATH=$APP_HOME/server
LOG_PATH=$APP_HOME/log
DIR_ARR=(${APP_HOME//// })
APP_NAME=${DIR_ARR[${#DIR_ARR[@]}-1]}
if [ $1 = "start" -o $1 = "restart" ] && [ $2 = "testing" -o $2 = "production" ];
then
echo "Will" $1 "server with environment > " $2
else
echo -e "\n \033[47;31m Usage: server.sh {start|restart} {testing|production} \033[0m \n"
echo "This shell shall only be executed for these situation:"
echo "1. First time to launch a server of project dev and built with vue-koa-boilerplate"
echo "2. Force restart the server. Will delete the original application in PM2"
exit -1
fi
cd $SERVER_PATH
case "$1" in
start)
echo "Luanching application server with PM2 for the first time..."
sleep 1
pm2 start pm2.json --env $2
echo "Commands of PM2 are available now."
;;
stop)
echo "This shell is not built for stop appliation."
echo "Please try pm2 stop" $APP_NAME
;;
restart)
echo "Force restating application..."
echo "Stop and remove application from PM2"
pm2 stop $APP_NAME
sleep 1
pm2 delete $APP_NAME
sleep 1
echo "Restarting application with PM2"
pm2 start pm2.json --env $2
echo "Commands of PM2 are available now."
;;
esac
exit 0
然后进入该文件目录运行 ./server.sh start/restart/stop testing/product服务就算是在后台运行起来了,命令窗口关闭也不影响~
常规的koa项目的后台目录大概是这样的
上测试了,还得修各种bug不是,但每次修改可能涉及多个文件,然后要挨个比对替换,比较繁琐,全局替换又觉得没必要,所以就邪念一起,准备把后端代码打包,常改动的文件就成一个文件了,每次只需替换改文件就搞定。
说来就来webpack配起来,像这样
function _externals() {
let dependencies = require('../src/server/package.json').dependencies
let externals = {
'any-promise': 'Promise'
}
for (let dep in dependencies) {
externals[dep] = 'commonjs ' + dep
}
return externals
}
const serverWebpackConfig = {
name: 'server',
devtool: false,
entry: [ './src/server/index.js' ],
output: {
path: config.paths.output,
filename: '[name].js'
},
target: 'node',
node: {
__filename: false,
__dirname: false
},
externals: externals,
module: {
loaders: [
{
test: /\.js$/,
loader: 'eslint-loader',
include: config.paths.server,
exclude: /node_modules/,
enforce: 'pre',
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.js$/,
loader: 'babel-loader',
include: config.paths.server,
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
}
]
},
resolve: {
extensions: ['.js', '.json']
}
}
const serverWebpackConfig = merge(baseWebpackConfig.server, {
output: {
path: config.dists.server,
filename: '[name].js',
chunkFilename:'[chunkhash].js'
}
})
package.json中加个命令,就把代码变成了这样
不管修改啥了,打个包,把main.js一替换,测试环境就搞定,当然要重启服务了
好像很完美的样子,但是呢,某天看到了PM2这个工具,又心痒痒了,什么并发、负载均衡、监测、守护、0秒重启,觉得看着挺像回事,是一个走向后台服务的亚子。那就试试咯
当然需要先安装PM2的环境了,然后代码进行一些调整,第一个启动服务当然还是那个脚本文件咯,但是文件的内容改了,大概是这样(当然里面的一些变量是可以根据配置文件生成的)
APP_HOME=$(echo `pwd` | sed 's/\/bin//')
SERVER_PATH=$APP_HOME/server
LOG_PATH=$APP_HOME/log
DIR_ARR=(${APP_HOME//// })
APP_NAME=${DIR_ARR[${#DIR_ARR[@]}-1]}
if [ $1 = "start" -o $1 = "restart" ] && [ $2 = "testing" -o $2 = "production" ];
then
echo "Will" $1 "server with environment > " $2
else
echo -e "\n \033[47;31m Usage: server.sh {start|restart} {testing|production} \033[0m \n"
echo "This shell shall only be executed for these situation:"
echo "1. First time to launch a server of project dev and built with vue-koa-boilerplate"
echo "2. Force restart the server. Will delete the original application in PM2"
exit -1
fi
cd $SERVER_PATH
case "$1" in
start)
echo "Luanching application server with PM2 for the first time..."
sleep 1
pm2 start pm2.json --env $2
echo "Commands of PM2 are available now."
;;
stop)
echo "This shell is not built for stop appliation."
echo "Please try pm2 stop" $APP_NAME
;;
restart)
echo "Force restating application..."
echo "Stop and remove application from PM2"
pm2 stop $APP_NAME
sleep 1
pm2 delete $APP_NAME
sleep 1
echo "Restarting application with PM2"
pm2 start pm2.json --env $2
echo "Commands of PM2 are available now."
;;
esac
exit 0
第一次启动,跟以前一样,之后的话,直接操作PM2的相关命令即可。
为了配个PM2的日志管理功能,需要对代码之前的日志功能进行一些调整
const logPath = process.env.NODE_ENV === 'dev' ? '../dist/log/' : '../log/'
const level = process.env.NODE_ENV === 'prod' ? 'INFO' : 'DEBUG'
// 之前的
export default {
appenders: [{
type: 'clustered',
appenders: [{
type: 'logLevelFilter',
level,
appender: {
type: 'dateFile',
filename: `${logPath}server.log`,
pattern: '-yyyy-MM-dd',
alwaysIncludePattern: false
}
}, {
type: 'logLevelFilter',
level: 'ERROR',
appender: {
type: 'file',
filename: `${logPath}server.log`
}
}]
}]
}
// PM2后
const envConf = process.env.NODE_ENV === 'development' ? {
appender: {
type: 'dateFile',
filename: './src/log/server.log',
}
} : {
appender: { type: 'console' },
replaceConsole: true
}
export default {
appenders: [
Object.assign({
type: 'logLevelFilter',
level: process.env.LOG_LEVEL || 'debug'
}, envConf)
]
}
大体就是把日志的输出变为console到PM2,然后PM2有自己的一套日志管理流程~。
涉及的部署的东西大概就这么多,打包的东西比较多,以后有机会说道说道~