pm2是node的进程管理器,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,它本身就是js写的。
pm2是既有服务端也有客户端,服务端就是进程,命令端是命令行。它里面有一种模式叫做守护进程模式(daemon_mode)它就是服务。这个守护进程就是pm2的核心,当然这里就需要去读取源码了。

模拟PM2拉起进程

  1. // app.js
  2. // worker
  3. var http = require("http");
  4. http.createServer(function(req, res){
  5. res.writeHead(200);
  6. res.end("hello world!\n");
  7. }).listen(8000);
  1. // manager.js
  2. var cluster = require("cluster");
  3. var munCPUs = require("os").cpus().length;
  4. if(cluster.isMaster) {
  5. console.log(munCPUs);
  6. for(var i = 0; i < munCPUs; i++) {
  7. var woker = cluster.fork();
  8. }
  9. } else {
  10. require("./app.js");
  11. }

manager用到了OS模块,它是跟操作系统相关的,都是封装操作系统的调用,里边的cpus是跟cpu相关的。cluster是涉及到进程实例的,也就是进程本身。在node api里面的叫法是集群。
调了OS的cpus就是返回了CPU核心的相关信息,返回的是一个数组,里边是一个个的对象。cpu有几个核就返回了几个对象。有几个核,就给它创建几个进程出来。把程序跑起来之后,进程的信息就保存在 cluster 里边。
所以整体代码可以理解为:首先要判断当前进程是否是主进程,如果是主进程。那么有几个CPU核心就创建(衍生)出几个工作进程。它的返回值就是进程id,PID。如果不是主进程,那么就需要子进程执行代码,子进程拉起app.js。但是为什么要这么做呢?实际上它是最大限度去使用cpu核心。

pm2部分核心运行机制:因为nodejs是IO密集型,尽可能的去减少进程的实例,一个核有一个实例就可以了。一个核配一个进程,最大限度的去使用cpu。如果只有一个进程,其他几个核都在闲着,这样不行,需要平均分配。进程在创建子进程的时候它要fork,主进程监控子进程。当fork的时候会把整个manager的代码复制出来一份给到子进程,循环1次就复制出一份。当循环完毕的时候主进程就在那卡住了,它不会退出的。如果退出,子进程会被销毁回收,然后整个程序也就退出了。子进程也是从第一行开始读取,然后执行。执行拉起app.js。子进程就是服务,在执行的时候会跳过循环。只执行自己的代码,也就是false里面的代码。有几个内核就拉起了几个子进程,所以说pm2是主进程,node是子进程。说白了就是给node分配了多少个子进程去工作。

PM2命令

  1. 启动进程/应用 pm2 start bin/www pm2 start app.js
  2. 重命名进程/应用 pm2 start app.js --name wb123
  3. 添加进程/应用 watch pm2 start bin/www --watch
  4. 结束进程/应用 pm2 stop www
  5. 结束所有进程/应用 pm2 stop all
  6. 删除进程/应用 pm2 delete www
  7. 删除所有进程/应用 pm2 delete all
  8. 列出所有进程/应用 pm2 list
  9. 查看某个进程/应用具体情况 pm2 describe www
  10. 查看进程/应用的资源消耗情况 pm2 monit
  11. 查看pm2的日志 pm2 logs
  12. 若要查看某个进程/应用的日志,使用 pm2 logs www
  13. 重新启动进程/应用 pm2 restart www
  14. 重新启动所有进程/应用 pm2 restart all