从 Supervisor 迁移到 PM2

Oct. 22, 2016, 3:23 p.m.
标签: tech

背景

之前一直用 Supervisor 来管理后台进程的启动和运行,一直用到了昨天。在使用的过程中我逐渐感受到了它的一些不足,这期间也尝试了一些其他的进程管理工具(CircusPM2),最后果断迁移到了 PM2 。

Supervisor

很久以前我就接触到了 Supervisor ,因为它是用 Python 写的,所以就从内心里给它加分了😂,然后一直简单地用它管理一些 Python 写的小服务,只需在 /etc/supervisord.conf 中配置好,就可以一键运行了,还是很方便的。

但其实,随着我的频繁变动,它的一些不足就暴露出来了,比如:

  • 不能快速查看 log ,需要设定日志文件,然后自己去查看文件内容。
  • 不能方便地监控进程的状态,只能看到进程是否在运行,以及运行的时长,没有更加详细的信息。
  • 以系统级服务的方式启动,没有用户的环境变量,所有路径都必须使用绝对路径。
  • 命令行功能太弱。

当然,也有可能是我使用的方式不对,不过文档我已经翻过好多遍了,supervisorctl也各种尝试各种manual了,如果这样还不能找到正确的使用方式,我只能说,我们不合适😌。

Circus

后来看到了一个后起之秀——Circus。这玩意儿也是用 Python 写的,支持 Python 3(Supervisor就不支持),据说有更加酷炫的操作界面,更加灵活的配置方式。

它最大的亮点是:Circus 本身只负责绑定端口和启动进程,所有的请求都直接转发给后面的 Worker 进程,而所有的 Worker 都是平等的关系(包括不同的服务和同一服务的多个进程),管理起来更加方便,所有进程的管理都在同一层面,相当于同时集成了 Supervisor 的全部功能 和 Gunicorn 的进程管理部分功能。而 Supervisor + Gunicorn 的组合中,需要由 Supervisor 来管理 Gunicorn,再由 Gunicorn 来管理下面的 Worker 进程。

此外,Circus是用户级的应用,因此启动进程时可以带上当前用户的所有环境变量。

然而,为了实现上述方案,必须要使用 Circus 提供的WSGI服务器 chaussette,而不幸的是,我的服务多使用 Python 3 的异步库 asyncio 实现,与 chaussette 不兼容。所以,还是只能使用 Circus + Gunicorn 的方案,与 Supervisor 并没有本质区别。

而且稍微使用了一下,感觉它毕竟是要和 Supervisor 竞争的产品,交互体验上也和 Supervisor 差不多,与 PM2 相比还是弱多了。

PM2

PM2 其实也用了一段时间了,它本身是用 JavaScript 实现的。我工作上写 Node.js 比较多,用 PM2 来调试和部署再方便不过了。相比之下,它有这些优势:

  • 使用 Node.js 安装,可以用用户权限运行,拥有当前用户的环境变量
  • 一键启动和重启应用,可通过 json/yaml 进行更多复杂的配置,功能非常强大
  • 快速查看log,还可以在命令行上监控进程的内存和CPU使用情况,界面酷炫
  • 可以将当前运行的所有进程及其环境保存下来,重启后一键恢复,避免启动环境变化带来的问题

于是果断迁移了过来,将所有需要经常使用的进程定义在一个 process.yml 里,然后 pm2 start process.yml 就好了,简直完美!