为什么守护进程只在启动时读取其配置文件?为什么他们不能对该文件/热重载中的更改做出“反应”?

为什么守护进程只在启动时读取其配置文件?为什么他们不能对该文件/热重载中的更改做出“反应”?

我知道必须向守护进程发送 HUP 才能使配置更改生效。但我想知道为什么会这样,以及是否可以创建一个响应此类更改的守护进程。

答案1

原因有多种。一个主要原因是许多守护进程有多个配置文件,并且任何单个文件更改都可能无法单独使用 - 因此,只要守护进程的配置文件之一发生更改,就尝试重新加载其配置,可能会导致比它解决的问题更多的问题。

从纯粹与实现相关的角度来看,必须监视配置文件的更改会增加守护程序的复杂性。守护进程有某种中央循环,检查与守护进程的核心目的相对应的要完成的工作;检查配置文件的更改并不一定适合该核心目的。

处理单独的信号解决了这两个问题:它表明用户认为配置是一致的,并且可以安全地重新加载,并且可以在信号处理程序中异步实现(通常作为基本标志更改),同时最大限度地减少影响在主循环上(它对标志更改做出反应)。

有些守护进程会自行对配置更改做出反应;cron例如,每次运行主循环时都会检查其配置文件是否发生更改。

答案2

除了其他答案中提到的所有其他原因之外,还有一个更深层的哲学原因,那就是基本的 Unix 编程设计原则之一:做一件事并把它做好

在 Unix 中,程序通常做一件事,而且只做一件事。通过组合多个程序可以实现更复杂的操作。

现在,为网站(例如)提供服务是一回事。观察文件的更改,这是另一回事。因此,根据 Unix 座右铭,这些应该是两个不同的程序,因为 Web 服务器例如为网站提供服务监视文件的更改是行不通的做一件事并做好,它会做两件事情。经常做两件事的程序至少在这两件事中做的不是很好。 (例如,编写 Web 服务器的人可能是 HTTP 方面的专家,但不是文件监视方面的专家。)

特别是对于面向网络的守护进程,还有另一个坚持“只做一件事”原则的原因:安全性。每一行代码都是潜在的错误。最安全的代码是没有代码。通过从守护进程中删除不属于该守护进程的职责,可以减少代码量,从而减少攻击面。

除了执行多项任务的程序通常会在其中至少一项上表现不佳之外,还有另一个划分职责的原因:代码重用。如果文件监视是 Web 服务器的一部分,那么您的 SSH 服务器也需要实现文件监视。还有你的文件服务器。还有你的聊天服务器。还有您的电话服务器。还有你的数据库服务器。以及您的媒体流服务器。等等等等。

而如果文件监视是一个单独的程序的责任,那么只需要实现这个程序一次,测试一次,优化一次,记录一次等等。你也只需要培训人们一次如何使用它,然后他们就可以应用它每一个曾经写过的守护进程,事实上甚至到未来将编写的每一个守护进程

所以,如果你想做你在问题中提出的问题,你会守护进程:例如,为网站提供服务的守护进程,以及监视文件更改并根据这些更改执行操作的守护进程。

而且,这样的守护进程已经存在,这可能不足为奇。

答案3

添加其他答案:最大的障碍之一是要求每个配置值都有一个解释,至少要了解应用程序的当前状态、先前的值和其他已更改的值。一般来说,配置文件指示守护进程如何从非运行状态进入其初始状态。对于守护进程在更改时重新加载其配置意味着还能够将配置值解释为对守护进程当前状态的修改。例如,让我们考虑某种任务守护程序。在它的配置中可能是worker_threads: 2.如果守护进程刚刚启动,解释很简单:创建两个线程来执行任务。如果您需要处理对该值的修改,现在您需要执行多项操作 - 如果线程数增加,请添加更多线程。如果减少,请删除一些线程。

对更改的解释不仅取决于先前的值,还取决于守护程序的当前状态。如果将配置更新为worker_threads: 1,那么如果两个线程都在使用,守护进程应该做什么?是否应该杀死一个人以立即匹配配置中描述的状态?是否应该允许任务运行完成然后终止一个线程?

除此之外,配置值更改的解释还取决于其他配置值的更改。假设有一个额外的配置值来确定当我们在所有工作线程都在使用时减少工作线程计数时要做什么:kill_threads_on_worker_reduction: true/false。如果设置好了,我们就可以确定是否杀死活动的工作线程。但如果该配置值是改变了?它仅适用于正在执行的新任务还是追溯适用于更改之前开始的任务?

这只是钻研可能的配置值。您必须针对每个配置值、每个可能的应用程序状态以及每个可能的更改值组合来计算出这一点。

虽然在某些情况下,配置更改的解释更加简单,但这有助于解释为什么实时重新加载配置更改通常不容易完成。

相关内容