{T}

服务自动化运维

项目开发完成后,如何高效、可靠地将其部署到生产环境,是保障服务质量的关键。本章将探讨如何利用 npm script 实现服务运维自动化,涵盖版本管理、服务部署、进程与日志管理等核心环节。

了解这些非前端的知识,能让你具备更全面的大局观,从容应对从开发到交付的全过程。

1. 自动化版本管理

规范的版本管理是项目迭代的基础。npm version 命令为我们提供了强大的支持。

遵循 SemVer 规范

我们推荐使用 Semantic Versioning (SemVer) 规范。你可以通过以下脚本轻松管理版本,并自动推送到 Git 仓库:

json
"scripts": {
  "release:patch": "npm version patch && git push && git push --tags",
  "release:minor": "npm version minor && git push && git push --tags",
  "release:major": "npm version major && git push && git push --tags"
}
  • npm run release:patch:发布修订版(例如 1.0.0 -> 1.0.1)。
  • npm run release:minor:发布次版本(例如 1.0.1 -> 1.1.0)。
  • npm run release:major:发布主版本(例如 1.1.0 -> 2.0.0)。

自定义版本规则

如果项目有特殊的版本需求(例如版本号不超过 10),你可以编写自定义脚本。以下是一个示例,它会在补丁版本达到 9 时自动提升次版本:

scripts/bump.sh 中添加(确保文件有可执行权限 chmod a+x):

bash
#!/usr/bin/env bash

version=$(cat package.json | grep version | awk -F\" '{print $4}')
components=($(echo $version | tr '.' '\n'))
major=${components[0]}
minor=${components[1]}
patch=${components[2]}

release='patch'

if [ $patch -ge 9 ]; then
    if [ $minor -ge 9 ]; then
        release='major'
    else
        release='minor'
    fi
fi

npm run release:$release

package.json 中配置 bump 命令:

json
"scripts": {
  "bump": "scripty"
}

注意:自定义版本规则可能会破坏 SemVer 的通用约定,请谨慎使用。

2. 服务部署与管理

我们将使用 pm2——一个功能强大的 Node.js 进程管理器,来实现服务的稳定运行和高效管理。

设置 Express 服务器

首先,我们需要一个简单的 HTTP 服务器来托管我们的应用。我们使用 express 提供服务,并用 morgan 记录访问日志。

安装依赖:

bash
npm install express morgan --save-dev

创建 server.js

javascript
const express = require("express")
const morgan = require("morgan")

const app = express()
const port = process.env.PORT || 8080

app.use(express.static("./dist"))
app.use(morgan("combined"))

app.listen(port, (err) => {
  if (err) {
    console.error("Server start error:", err)
    process.exit(1)
  }
  console.log(`Server started at port ${port}`)
})

使用 PM2 进行进程管理

pm2 提供了进程守护、负载均衡、日志管理等丰富功能。

安装 pm2

bash
npm install pm2 --save-dev

创建 pm2.json 配置文件,以声明方式管理服务:

json
{
  "apps": [
    {
      "name": "npm-script-workflow",
      "script": "./server.js",
      "out_file": "./logs/stdout.log",
      "error_file": "./logs/stderr.log",
      "log_date_format": "YYYY-MM-DD HH:mm:ss",
      "instances": 0,
      "exec_mode": "cluster",
      "max_memory_restart": "800M",
      "merge_logs": true,
      "env": {
        "NODE_ENV": "production",
        "PORT": 8080
      }
    }
  ]
}

配置解析

  • instances: 0pm2 会根据 CPU 核数自动创建相应数量的进程。
  • exec_mode: "cluster":开启集群模式,实现负载均衡。
  • env:为生产环境注入环境变量。

配置部署脚本

我们将部署流程封装在 npm script 中,实现一键部署。

json
"scripts": {
  "predeploy": "npm install && npm run build",
  "deploy": "pm2 restart pm2.json"
}
  • predeploy:在部署前自动安装依赖并执行构建。
  • deploy:使用 pm2 重启服务,应用最新代码。

现在,只需运行 npm run deploy 即可完成整个部署过程。

日志管理

虽然 pm2 logs 可以查看日志,但当服务器上运行多个服务时,日志会混合在一起。我们建议为当前项目配置专用的日志查看命令。

首先,创建日志目录并将其添加到 .gitignore

bash
mkdir logs
touch logs/.gitkeep

.gitignore:

code
dist
logs

然后,在 package.json 中添加 logs 脚本:

json
"scripts": {
  "logs": "tail -f logs/*"
}

运行 npm run logs 即可实时查看当前应用的所有日志。

3. 安全与性能考量

  • 环境变量:切勿将敏感信息(如 API 密钥、数据库密码)硬编码在代码中。使用 .env 文件或系统环境变量,并通过 pm2.jsonenv 字段注入。
  • 日志轮转:生产环境的日志文件可能会迅速增长。考虑使用 logrotatepm2-logrotate 等工具来管理日志文件的大小和归档。
  • 资源限制:在 pm2.json 中设置 max_memory_restart,以防止内存泄漏导致服务崩溃。

总结与最佳实践

通过本章的学习,你已经掌握了如何利用 npm script 和 pm2 实现自动化、高可用的服务运维流程。

核心要点

  • 版本管理自动化:使用 npm version 结合 Git 操作,简化发布流程。
  • 声明式进程管理:通过 pm2.json 配置文件,确保服务配置的一致性和可复现性。
  • 部署流程脚本化:将构建、安装、重启等步骤封装在 npm script 中,实现一键部署。
  • 独立的日志管理:为每个项目配置独立的日志查看命令,便于问题排查。

将这些实践应用到你的项目中,将极大提升你的开发与运维效率。


本节用到的代码见 GitHub。建议边看边动手练习,注意切换到正确的分支 13-use-npm-script-for-devops