一、前言
作为一个web前端开发,不可避免的会接触到一些偏后端的项目,刚好可以用nodejs开发。 其实开发都没什么问题,关键是如何部署呢?保证系统稳定性呢?
二、Nodemon开发环境启动
以Express框架为例,我们通过官方脚手架,新建一个Express项目。目录结构如下:
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug
复制代码
项目启动的脚本在bin\www
文件,因此开发环境,我们启动项目时,直接项目在根目录下,执行:
node ./bin/www
复制代码
即可启动成功。
但是问题来了,这个没法达到热更新部署的效果。也就是本地调试代码的时候,改了文件,它不会自动重启。所以,我们要用到Nodemon
:
Nodemon is a utility depended on by over 1.5 million projects, that will monitor for any changes in your source and automatically restart your server. Perfect for development. 上述是官网的介绍,主要就是说,Nodemon能监控到任何文件的修改变动,并自动重启服务。完美的适配于开发环境。
用法也及其简单:
npm install -g nodemon
复制代码
然后再执行启动命令
nodemon ./bin/www
复制代码
三、测试及生产环境pm2启动
这个时候就涉及到几个简单的问题要解决:
- 环境变量注入
- 应用进程的稳定性
- 日志查看
这个时候
pm2
就派上用场了,
PM2 is a daemon process manager that will help you manage and keep your application online 24/7 简单翻译过来,就是pm2一个是常驻后台的,能够帮助和保持你的应用7x24小时在线的进程管理工具。 根据官方文档,我们可以知道它实现的功能如下:
- 进程管理和监控(cpu、内存等),支持多个应用,支持其他语言的启动脚本
- 配置文件,支持设置环境变量、服务名称、入口文件等,支持自动部署,一键部署到生产环境(可以配置 ssh 自动登录)
- 日志管理,功能比较强大,支持 console 输出的日志
- cluster mode,可自定义instances数量,支持 reload
- 提供入口点钩子函数4个方法:onStart,onStop,sensors,actuators 。。。。。。等等。 总之,它就是功能强大,且上手简单,傻瓜式的上手。
使用起来也很简单,首先是全局安装:
npm install -g pm2
复制代码
再编写配置文件,设置环境变量,根目录下新建一个ecosystem.config.js
:
module.exports = {
apps: [{
name: "your_app_name",
script: "./bin/www",
watch: true,
env: {
"PORT": 3006,
"NODE_ENV": "development",
"DOMAIN": "http://xxx.xxx.xxxx"
},
env_uat: {
"PORT": 3006,
"NODE_ENV": "uat",
"DOMAIN": "http://xxx.xxx.xxxx"
},
env_production: {
"PORT": 3006,
"NODE_ENV": "production",
"DOMAIN": "http://xxx.xxx.xxxx"
}
}]
}
复制代码
在package.json
编写启动脚本
"scripts": {
"dev": "cross-env NODE_ENV=development DEBUG=app-server nodemon ./bin/www --name 'app'",
"start": "pm2 start ecosystem.config.js --env production",
"uat": "pm2 start ecosystem.config.js --env uat"
},
复制代码
这样,我们在控制台执行npm run uat
,那么pm2就帮我们取到uat的配置,来启动服务了。
注意: ecosystem.config.js配置文件里面的env_xxx 这个写法固定,对应你命令行里面的--env xxx
pm2 常见命令
pm2 list
:查看pm2守护的node所有的应用列表pm2 logs
:查看日志pm2 restart [id]
:重启[id]服务 更多命令,可以查看官网的文档。
四、为什么使用Systemd启动应用?
之前我们讲到了一些pm2的特点和实现的功能,其实挺全面的。中小型项目用pm2完全没问题。 如下问题我们需要仔细考虑下:
- 大多数pm2提供的功能,我们也用不到。
- pm2需要额外安装
- 从运维的角度来说,怎样便统一管理和项目启动的脚本。java项目怎么启动?nodejs项目怎么启动,python项目怎么启动?各搞各的,自动化部署方面也存在一定的麻烦。
因此,统一所有的项目启动和进程守护方式,我们可以从Systemd
入手。
systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。
根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。我们常见的应用部署到系统发行版都是centOS 7以上的。那么这种系统本身就自带了systemd了,所以我们不需要额外再去安装pm2,再通过pm2来守护进程。
Systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。现在还有很多人反对使用 Systemd,理由就是它过于复杂,与操作系统的其他部分强耦合,违反"keep simple, keep stupid"的Unix 哲学
五、如何使用systemd
systemctl
是 Systemd
的主命令,用于管理系统。
以上述的nodejs项目为例,我们将去pm2,直接通过systemctl启动。
1、新增启动配置
首先、进入到/etc/systemd/system
目录下,新增一个serve文件,取名rock-app.service
,编辑配置文件内容如下:
cd /etc/systemd/system
vi rock-app.service
复制代码
编辑rock-app.service内容如下:
[Unit]
Description=
Documentation=
[Service]
Type=simple
Environment=PORT=3006
Environment=NODE_ENV=uat
Environment=DOMAIN=http://xxx.xxxx
WorkingDirectory=/home/apps/rock-app
ExecStart=/usr/bin/node bin/www
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target
复制代码
需要注意的是:
Environment
就是之前的ecosystem.config.js
里面的环境变量WorkingDirectory
是要设置为你nodejs应用的根目录。ExecStart
是你启动命令。也就是我们通过/usr/bin/node bin/www
来启动。这里识别不了全局的node命令,只能通过/usr/bin/node
来识别。
2、启动命令并查看应用服务状况
启动应用:
systemctl start rock-app
// 或者 systemctl start rock-app.service
复制代码
查看应用状态:
systemctl status rock-app.service
复制代码
可以看到该服务处于active
状态。
如果我们后续有修改到rock-app.service这个配置,需要先执行一个命令:
systemctl daemon-reload
复制代码
再重启服务
systemctl restart rock-app
复制代码
查看日志命令,我们可以通过系统自带的journalctl来查看:
// 基本命令
journalctl -ex -u rock-app.service
// 过滤时间
journalctl -ex -u rock-app.service --since "2018-01-10" --until "2019-01-11 03:00"
// 过滤时间
journalctl -u rock-app.service --since today
复制代码
更多命令,可以参考此处systemd入门。
六、结语
艺多不压身,守护nodejs进程,我们又多了一种方式systemd
。
此前我们写在应用代码中的环境变量一些启动配置,通过systemd强关联耦合到了服务器上了。方便了开发和运维的职责分离。项目的开发交给开发人员,项目的启动运维,交给运维人员。开发提供最新的配置文件给到运维。但这个过程中也增加了一些配置文件修改的沟通成本。
但是这种方式是否真的合适,具体得根据项目大小,团队开发运维的方式来定。
对于顶尖的技术团队而言,多进程模型(Master-Worker-Agent)是PM2无法支持的。
对于监控功能有更高要求的,pm2支持也不太友好。
但是我们掌握到了linux系统底层的,或者自带的类似systemd
这种管理进程的工具的使用,我们才能知道如何去封装自己的进程守护工具。