forever 与 pm2
在之前部署 Node.js 服务都是使用 forever 的,现在基本上都改为 pm2 了,pm2 比 forever 功能更加强大,可以配置集群、集成日志、控制台监视等等,下面是两者的比较:
| Feature | Forever | PM2 |
|---|---|---|
| Keep Alive | ✔ | ✔ |
| Coffeescript | ✔ | |
| Log aggregation | ✔ | |
| API | ✔ | |
| Terminal monitoring | ✔ | |
| Clustering | ✔ | |
| JSON configuration | ✔ |
所以如果还在使用 forever 的读者,快快加入到 pm2 的阵营来吧。
pm2 使用
详情请看官方文档
配置
pm2 可以直接在命令行中通过参数配置,也可以用过 ecosystem.config.js 文件来配置,pm2 init 初始化一个配置文件如下:
1 | module.exports = { |
集成 log
可以单独配置普通输出和错误输出到不同的文件:
1 | module.exports = { |
同时也可以集成 pm2-logrotate 工具来管理日志,可以配置日志分片大小、时间、名字等等。
自启动
pm2 可以配置开机启动,通过 pm2 startup 命令会自动提示你该怎么配置自启动。
负载均衡
pm2 支持集群模式,可以在不更改代码的前提下自动帮你配置集群,有效利用系统的 CPU 资源,充分利用计算机能力,消除 Node.js 单线程的瓶颈,可以同时启动多个进程来监听同一个端口(这在文后会提到具体怎么实现多进程监听),提高性能。
1 | -i <number-instances> |
或者配置 ecosystem.config.js 文件:
1 | module.exports = { |
SSH 部署
pm2 还支持自动化将代码部署到远程服务器,只需要做一些简单的配置即可。
1 | module.exports = { |
注意事项
- 如果使用集群模式需要主要应用得是个无状态应用,所以诸如
sessions、websocket connection等不要使用,可以使用Redis等来共享应用的状态。 - 关闭应用之前最好确认所有的请求已经被处理,数据库连接已经释放,释放其他资源。
cluster 原理
pm2 集群其实是封装了 cluster 模块的一系列操作,自动包装代码启动集群,重加载的时候也是先启动新的 worker 再把之前的 worker 停掉等等。
这里是一个简单的 cluster 的示例:
1 | const cluster = require('cluster') |
fork 的本质还是使用了 child_process.fork 生成的子进程,但是注意不能直接使用 child_process.fork() 来生成,因为这样会缺少 process.env.NODE_UNIQUE_ID,会导致 cluster.isMaster 判断总是为 true。
运行时,所有新建立的连接都由主进程完成,然后主进程再把 TCP 连接分配给指定的 worker 进程。分配根据 Round-robin 算法分发,子进程 worker 具体处理请求。