node服务的部署流程演进--从多文件到打包后的单文件,从命令行启动到PM2

做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项目的后台目录大概是这样的

node服务的部署流程演进--从多文件到打包后的单文件,从命令行启动到PM2_第1张图片

上测试了,还得修各种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有自己的一套日志管理流程~。

涉及的部署的东西大概就这么多,打包的东西比较多,以后有机会说道说道~

你可能感兴趣的:(node服务的部署流程演进--从多文件到打包后的单文件,从命令行启动到PM2)