管理服务器进程的正确方法

Kangle一键安装免费商业版系统脚本    2022-07-16    212

在完成网站开发并将其部署到要服务的生产服务器时要考虑的问题之一是如何启动需要在服务器上启动的各种进程。当然,进程死掉时也需要重新启动进程。monitsupervisordgod用于此目的(还有几个其他目的)。但这是因为对操作系统缺乏了解。进程管理是操作系统的核心功能。在这项研究中,我们将讨论为什么 monit 是错误的选择以及正确的方法是什么。

工艺编号1 初始化

正确的方法是使用操作系统的初始化系统,或类似的替代系统。init 是在 Unix 上启动时创建的第一个进程。因此,进程号为1,所有后续进程都成为init进程的后代,系统启动时启动的所有进程都由init启动。设置为重生的进程也会在它死亡时重生。那么,如果您需要在服务器上启动一个进程,将它留给 init 不是很自然吗?

当然init系统老了,也有问题,但是开机过程有大问题,进程管理没有问题。然而,这有点麻烦。有关用法, 请参阅使用 init 脚本管理 Linux 守护程序。如您所见,这有点烦人。

但是现在这个初始化系统将载入史册。不,它已经从许多 Linux 发行版中消失了。Ubuntu 多年前就已经用upstart取代了init ,其他发行版已经转移到systemd,最近 Ubuntu 也加入了 systemd 。所以,未来在 systemd 中,如果您需要在服务器上启动和管理进程,使用 systemd 就是答案。

从monit开始的黑历史

但是为什么有init的时候会出现monit这样的工具呢?这里有一些历史。几年前,monit 开始在 Ruby on Rails 开发人员中流行起来。在 Rails 出现之前,Web 开发的主流是 PHP 和 Java,但 PHP 是作为模块附加到 Apache 的,所以不需要单独管理进程,Java WAS 有自己的进程管理。因此,Web 开发人员可能没有太多机会考虑如何启动、关闭和重新启动服务器上的进程。引领当时 Web 开发时代的并不是之前沉迷于 Unix/Linux 的黑客。

在这种情况下,Rails 诞生了,但是没有可以运行 Rails 的应用服务器,所以Ruby 开发者自己做了一个像mongrel一样的服务器。但是,像Java WAS那样开发安装整个进程管理功能并不容易(当然,这不是一个好方法),而且由于Rails还不够稳定,杂种进程经常死掉。于是萌生了监控进程的想法,看是不是死掉了,死了就保存,结果就是monit。monit 之所以流行,是因为它改善了 Rails + mongrel 组合的不稳定性。

问题是,正如我们之前看到的,我们不需要 monit,因为我们已经有一个用于此目的的 init 系统。显而易见的是ReinventTheWheel。当然,轮子可以通过改进它来重新发明。但是,monit 比 init 更慢、更消耗资源且更不稳定。在 running-processes 中,表示如下。

Wow. You reinventedinitandcron, but managed to make them both less reliable and consume more CPU than I could’ve imagined.

监控的接口

但 monit 一定有话要说。当时upstart还处于起步阶段,没有systemd,init的问题早就被指出了(不管是不是进程管理)。而且,init的设置方式也远非Ruby开发者的口味。正如您在使用 init 脚本管理 Linux 守护进程中看到的那样,/ etc/init.d 中的脚本不是很漂亮。这可能与 喜欢ReinventTheWheel的 Ruby 开发人员的倾向一致。

并且 monit 有一个 init 没有消化的函数。当进程终止时,它会通过电子邮件等方式发送通知(当然,这并非不可能,但至少它不是 init 的功能)。这两个至少是监视的借口。

Unix哲学

然而,这个借口是不够的。Unix 软件反映了与一般用户使用的软件不同的哲学。与服务于多种用途的用户应用程序不同,Unix 程序不服务于多种用途,它们只做一件事,但旨在最好地完成工作。通过管道、重定向和信号等基本方式组合这些程序,您可以做复杂的事情。但是,monit 结合了在进程死亡时恢复进程并通知开发人员的任务。当时Unix已经有很多比较好的监控工具,所以monit的监控功能并不是很好。所以,我把这两个工作放在一起,这两个工作都比最初存在的其他工具更糟糕。因此,在您想要击败这两个目标的情况下,有一些优势,但作为回报,您会使用大量系统资源并获得更差的监控服务。

但是,如果 monit 只专注于通过专注于 Unix 哲学来管理流程,就像我之前所说的那样,它就变成了一个完整的 ReinventTheWheel,毫无用处。Supervisord 就是这样。supervisord 是 init 功能的一个子集,但在较低的性能水平上,它是纯粹的、纯粹的盈余。

上帝比monit走得更远。它有许多强大的功能,因此很难将它们与 monit 或 supervisord 捆绑在一起。因此,如果您专注于流程管理以外的目的,那么您可能会接受它,但这提出了一个问题,因为仍有许多更好的工具。

此刻回答

upstart

尽管已经决定过渡到 systemd,但许多发行版仍然默认提供 upstart。您仍然可以使用 systemd,但现在,您可以简单地继续使用基本的 upstart 并应用 systemd,同时应用 systemd 更改为默认值的发行版。那么,让我们来简单看看如何使用 upstart。

upstart/etc/init可以通过在 . 我们来看一个celery的例子,它被广泛用作任务队列。celery 服务器通常使用以下命令启动。

celery -A myapp.tasks worker -l INFO -E

这将启动一个处理工作的工作进程。如果你想用 upstart 管理它,请/etc/init/celery.conf按如下方式创建文件。

Celerydescription"Celery Worker"startonrunlevel[2345]stoponrunlevel[06]respawnlimit105scriptchdir/home/ubuntu/myprojectexecsudo-uwebusercelery-Amyapp.tasksworker-lINFO-E>/home/ubuntu/logs/celery.log2>&1endscrip

与 init 不同,您不需要授予执行权限。然后像这样启动服务器:

sudo start celery

关机和重启如下。在Ubuntu的情况下,它很方便,因为它会通过按Tab键自动完成可以启动哪些服务。

sudo stop celery sudo resart celery

在上面的配置文件中,respawn部分就是死后要再次执行的设置。死亡后,以 5 秒间隔开始重试,最多 10 次。在脚本部分编写要实际执行的代码。

一个警告是,与 cron 类似,不会加载环境变量。如果依赖locale等环境变量,则必须指定LC_ALL等环境变量。

系统

如果说新贵是现在,那么 systemd 就是未来。由于未来大多数Linux发行版都会集成到systemd中,因此提前学习systemd会很好。当然,即使是现在,即使 systemd 不是默认的,大多数最新的发行版也会安装,即使没有安装,它也会作为包安装。如果你看一下 sshd 的例子会更容易理解。在Ubuntu发行版中,/etc/systemd/system/sshd.service文件是这样写的:

[Unit] Description =OpenBSD Secure Shell server After =network.target auditd.service ConditionPathExists =!/etc/ssh/sshd_not_to_be_run [Service] EnvironmentFile =-/etc/default/ssh ExecStart =/usr/sbin/sshd -D $SSHD_OPTS ExecReload =/bin/kill -HUP $MAINPID KillMode =process Restart = on -failure [Install] WantedBy =multi-user.target Alias =sshd.service

启动、重启等。

systemctl start sshd .service systemctl stop sshd .service systemctl restart sshd.service

为什么社区选择 systemd

但是,为什么 init 的替代方案 upstart 已经问世并经过多年验证,但为什么 systemd 出现并取而代之?当然,推动暴发户的 Ubuntu 并不想转用 systemd,但Ubuntu 的母体 Debian 社区决定转用 systemd,所以 Ubuntu 也顺势而为。那么,upstart 尝试改进 init 的哪些方面,systemd 不喜欢 upstart 的哪些方面?

init 的最大缺点是任务并行运行。所以,如果有很多 I/O 作业,启动速度会很慢。因此,upstart 是基于事件编写,并异步处理任务。并且比起sysv init,它更容易设置。根据我的经验,它比 systemd 更容易,但在这一点上似乎存在分歧。

然而,随着这个新贵遍布多个发行版,它开始受到批评。其中,最详细的解释是Rethinking PID 1。在本文中,我们首先定义了一个好的 init 系统应该具有以下特征。

少开始尽可能并行处理

但是upstart是可以设置依赖的,所以如果服务之间设置了依赖,是按照依赖的先后顺序执行的。最多应用异步逻辑,但最终需要序列化,这降低了性能增益。并且,由于不立即需要的服务也被上传,所以从一开始就会出现许多进程。另一方面,systemd 可以按需运行许多服务。例如,sshd 在启动时不会启动,而是在向端口 22 发出请求时启动。依赖也是这样设置的。因此,启动速度快,不增加不必要的服务,节省系统资源。从管理应用服务器进程的角度来看,节省系统资源也是有益的。从这个角度来看,monit 和 supervisord 仍然是多余的。

辩论 init system提供了 init、systemd 和 upstart 的详细比较,因此阅读本文会很有趣。

追求正确的方式

前面解释了monit出现的历史背景。但是,我想向前迈进,讨论态度问题。为什么 monit 或 supervisord 开发人员会不理会 init 并开发这样的东西?我认为这是解决问题的优先事项。如果你只专注于解决眼前的现状,就会想到这样的解决方案。monit 开发人员在遇到的情况下问了哪些问题?可能不是启动 unix 进程的正确方法。是不是更像是如何确定一个进程是否正在运行,或者如何重新生成进程?因此,收集此类问题的个人答案将有助于开发 monit。手头的问题就这样解决了。欢呼。

我认为这是工程师的态度问题。工程师本能地专注于解决他们面前的问题。这是个好姿势。然而,它不应该止步于此。尽管如此,您仍必须继续怀疑并思考什么是正确的做法。如果您查看与 monit 或 supervisord 相关的问题,您会发现一个有趣的事实。这意味着 monit 自己的进程必须在使用 monit 启动的进程之前浮动。那么我如何保持 supervisord 浮动?同样的问题经常出现。因为你不能让 supervisord 作为 supervisord 浮动。如果你仔细想想,即使你不知道init, 你也能猜到OS中一定有什么东西在启动一个进程中起作用。并且 init 或 upstart 总是在答案中运行,因此查看答案,您可能会认为让 supervisord 完成 init 或 upstart 的工作是可以的。但是为什么我们不能想到这个想法呢?这是因为重点只放在手头的任务上。如果我退后一步,有时间思考,supervisord 就不会来了。

对于那些了解我的想法,坚持精益创业并强调专注于手头任务的人来说,追求这种正确的方式可能看起来很尴尬。但正确的方法是正确的方法,因为它更有效率。如果主管开发人员考虑一下正确的方法是什么,而不是尝试通过自己开发来解决问题,他们会更快地解决问题,因为他们在执行时只需要创建一个简单的配置文件。开发 supervisord,解决方案的质量也会好得多。

一直专注于解决当前问题的开发人员积累了奇怪的诀窍,因此往往很难通过留下简单的方法而使用困难的方法来维护,或者通过自己的库解决问题。另一方面,一直在追求正确方法的开发者 通常会选择更简单、更高效的方法,因为他们了解平台的特性并尊重约定 。让monit、supervisord、god流入历史,作为审判之石。

网友评论