如何在PHP中对Unix信号处理进行可靠的集成测试?

问题描述:

我在写一个在后台运行的服务器系统。简而言之,它有它自己的脚本语言,这意味着一个进程可以用该语言编写以独立运行,或者它可以调用另一个进程等。我将这个系统从一个简单的PHP cron-job转换成一次只允许一个实例进入由Supervisor管理的一组长时间运行的进程。考虑到这一点,我知道这些过程可以在任何时候被杀死,无论是由我自己开发,还是由Supervisord在正常停止或重新启动工人过程中。我想添加一些适当的信号处理,以确保工作人员自行收拾,并在适当的时候记录任务处于中断状态。如何在PHP中对Unix信号处理进行可靠的集成测试?

我已经制定了如何使用蜱和pcntl_signal()来启用信号处理,并且我的处理目前似乎工作正常。但是,我想对此进行测试以确保其可靠。我已经写了一些早期的集成测试,但他们并没有感觉到那么扎实,主要是因为在开发过程中出现了各种各样奇怪的种族条件问题,这些问题很难确定。

我想就如何在PHPUnit测试中发送kill信号提出一些建议或方向,以期提高我的信号处理功能的可靠性。我目前的策略:

  • 使用PHPUnit的
  • 为核心的系统运行时,它创建日志各种文件,它可以被用来监视时杀死
  • 核心系统是利用发射任务在PHPUnit测试中使用system()命令在后台分离PHP脚本。我的命令与php script.php > $logFile 2>&1 &类似,即将所有输出重定向到日志文件,然后将其推送到后台,因此测试方法可以监视它
  • 后台脚本将其PID写入文件,该文件将成为要杀死的PID
  • 这被可靠地通过扫描反复拾取的测试为它和扫描之间荷兰国际集团usleep
  • 测试然后通过扫描数据库,usleep扫描之间ING,并发出kill <pid>,当它准备好用于特定状态等待
  • 然后它等待信号处理程序启动并写入新的数据库状态,以避免火腿使用数据库
  • 最后,它会确定数据库是否处于正确的状态,在经过/未通过测试的最大延迟时间之后。

当然,所有这些等待/检查,感觉有点rope,,而且对于各种各样的竞赛条件来说都相当成熟。我目前的感觉是,测试将在大约2%的时间内失败,但我无法在一天左右的时间内使测试失败。我打算做一些沉浸测试,如果我得到任何失败,我会在这里发布。

我想知道我是否可以通过询问被测系统到kill本身来简化它,它将移除两个级别的等待检查(一个等待PID,另一个等待数据库进入正确的状态在杀死命令之前)。在发布kill之后,这仍然会等待检查循环,但我可能会发现在实践中使用这种检查并不是问题。

这就是说,我意识到我的整个方法可能会受到阻碍,并且有更好的方法来做这种事情。有任何想法吗?目前我的想法是增加我的等待超时,以防PHPUnit引入任何奇怪的延迟。我还会看看是否可以通过失败案例来检查日志。


†啊,可惜它不会简化很多东西。我只是尝试了一个简单的信号集成测试,我认为它是可靠的,并且由于后台接口system()立即返回,它仍然需要循环等待以识别正确的日志记录,然后再进行正确的后处理结果。但是,它不再需要等待将PID写入临时文件,这样至少可以消除一个循环。

+0

可能的方式来广泛。 – 2016-08-16 21:26:02

+0

我可以看到有人可能会认为它是一个边缘案例。不过,我想知道这看起来是否过于宽泛,因为矛盾的是,我指定了太多细节?简而言之,它需要一种方法让涉及Posix信号的测试更可靠 - 我希望这里有人可能有一些经验!我们拭目以待... – halfer

正如我在问题中提到的那样,我尝试的第一个可靠性更改是为工作任务注入能力,以便自己运行kill。在我的情况下,这是内置在系统中的,但读者可能会发现编写一个儿童测试课并更改他们的DI配置将是一个方便的方法。

这似乎提高了可靠性很好。原来,有在测试几个等待循环,测试必须在正确的时刻运行kill

  1. 等待孩子的PID变为可用
  2. 等待子日志文件以表明它已准备好要杀死
  3. 问题的kill
  4. 等待子日志文件指示信号处理程序正确运行

的问题可能已经在(2) - 如果这个值太短,那么kill有时会到达太晚,即使发现可靠的最大等待时间,如果CPU处于意外负载下,它仍然可能会出现故障。

我现在已经写了一个快速脚本来重复运行PHPUnit测试,无论是200次迭代还是第一次失败,以先到者为准。现在通过了200次迭代,所以暂时我认为测试的可靠性已经提高了。不过,如果这种情况发生变化,我会在这里更新 - 也许运行高测试的测试会触发失败。

其他答案仍然是最受欢迎的。