预计阅读时间: 4 分钟
无论是Systemd和Supervisord都可以用于控制进程,实现进程的分组管理和崩溃自动重启,下面我们看看他们都是怎么实现的。
进程控制
无论 Supervisord 还是 Systemd,都采用 ini 作为配置文件的格式。跟 Supervisord 不同的是,Systemd 每个程序都要单独开一个 unit 文件。
Supervisord 可以同时启动/停止配置文件中所以的进程(或者某个进程组配置中的进程)。
也就是说,Supervisord 使用“进程组”这个概念来控制多个进程
Systemd 则用用依赖来实现这一点。
我们来看一个简单的Systemd配置文件,实现了进程组管理
; group.target
[Unit]
Description=Application
Wants=prog1.service prog2.service
; prog1.service
[Unit]
Description=prog1
PartOf=group.target
[Service]
ExecStart=/usr/bin/prog1
Restart=on-failure
; prog2.service
[Unit]
Description=prog2
PartOf=group.target
[Service]
ExecStart=/usr/bin/prog2
Restart=on-failure
systemctl start group.target
,prog1 和 prog2 也会启动。systemctl restart group.target
,prog1 和 prog2 也会跟着重启
相比起来Supervisord的管理方式就要明了一些了
[program:prog1]
command=python /home/user/myapp/prog1.py
[program:prog2]
command=python /home/user/myapp/prog2.py
[group:prog]
programs=prog1,prog2
supervisorctl start prog:*
可以启动prog组下的所有进程
如果要更改 supervisord 的配置文件,supervisord 需要运行 supervisorctl reread 才会生效。
而 systemd 则需要 systemctl daemon-reload。这方面两者差不多
不过 supervisord 有一个优点。如果你不知道哪些程序的配置改变了,简单地执行 supervisorctl update,所有涉及的进程都会被重启。
而 systemd 貌似做不到这一点。
systemd 可以指定 stop 操作时可以选择的命令(ExecStop=)。另外它还提供了 ExecReload=,可以自定义调用 systemctl reload xxx 重新读取程序配置文件时的操作。
supervisord 不支持 reload 指定进程。同时对于 stop 操作,它只允许你选择要发送哪种信号…
supervisord 的 stopwaitsecs 可以控制 stop 操作后等待程序退出的耐心(以秒衡量)。待给定的耐心都消耗完毕后,supervisord 才会痛下杀手,发送 SIGKILL。
systemd 对应的配置项是 TimeoutStopSec=。systemd 会给多一次机会,在下最后通牒之前,会先发送 SIGTERM,过另一个 TimeoutStopSec 之后才发送 SIGKILL。
对比
systemd 和 supervisord 各有长短,不存在哪一方绝对的碾压。
systemd 跟 Linux 紧密结合,主流的发行版几乎全部使用systemd,所需的依赖少,其提供的保障自然比 supervisord 更可靠。然而在强大的能力背后,也有配置复杂、不易上手等问题。
systemd使用C语言编写,启动速度要快于supervisor,因此底层和对可用性有较高要求的情景,systemd还是更加适应的。
supervisord 偏于应用层,却因此有独特的用武之地。
举个例子,许多人会往 docker 打包里面封入一份 supervisord,让它来做 PID 1,以此稍微增强下健壮性。
supervisord还有XMLRPC接口,使得它和上层应用更容易结合,无论是否是Python应用。
换 systemd 做同样的事,就像用园艺剪刀裁纸,即使能够顺利完成,也难免事倍功半。毕竟这样的方式跟 systemd 的设计是背道而驰的。
至于健壮性的对比,我没有做过实验不知道,但两者都是经过多年检验过的项目,健壮性对于小型服务来说都是足够好的了。