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
具体处理请求。