PHP 5.5+ Opcache 究竟何时根据revalidate_freq设置检查文件时间戳


When exactly does PHP 5.5+ Opcache check file timestamp based on revalidate_freq setting

之前/其他地方已经问过这个问题,但我找不到答案。

我们在部署后的几分钟内遇到了一些问题,我们认为它们与 Opcache 相关。在我们的实时设置中,我们有以下操作缓存设置:

opcache.revalidate_freq=60
opcache.validate_timestamps=1

PHP 执行以下哪项操作?

  1. 当 PHP 需要一个文件时,它是否检查自上次生成文件的新缓存以来是否已过 60 秒,如果它已经更多,然后为此请求生成一个新缓存?

  2. 或者它是否在某种形式的计时器(或其他东西(上运行,其中 60 秒与上次需要文件的时间无关?

我希望选项 1,但这并不能解释我们 60 秒左右的问题,因为我们每次部署到交替的 A 或 B 目录时,文件的文件路径是不同的。

我希望这是有道理的?感谢您的帮助。

根据我对 PHP 源代码的分析,会发生什么类似于选项 1 的情况。当 PHP 需要文件时,它会检查自上次编译或重新验证文件以来是否已opcache.revalidate_freq。如果没有,它将跳过重新验证(时间戳检查(。

换句话说,opcache.revalidate_freq设置指定时间戳检查的最大频率。在请求文件之前不会重新验证文件,即使距离上次重新验证已经过去了一年。

下面是 ZendAccelerator.c 中处理缓存验证的 C 函数:

int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle)
{
    if (persistent_script->timestamp == 0) {
        return SUCCESS; /* Don't check timestamps of preloaded scripts */
    } else if (ZCG(accel_directives).revalidate_freq &&
        persistent_script->dynamic_members.revalidate >= ZCG(request_time)) {
        return SUCCESS;
    } else if (do_validate_timestamps(persistent_script, file_handle) == FAILURE) {
        return FAILURE;
    } else {
        persistent_script->dynamic_members.revalidate = ZCG(request_time) + ZCG(accel_directives).revalidate_freq;
        return SUCCESS;
    }
}

脚本成功重新验证时,即当 PHP 检查文件的时间戳并发现自文件放入缓存以来它没有更改时,它会将文件标记为"新鲜"opcache.revalidate_freq秒(.revalidate 属性(。这将防止在该时间段内进行进一步的时间戳检查(PHP 将假定文件是最新的(。

如果重新验证不成功 - 即时间戳比缓存中的时间戳新,这会导致重新编译,这也设置了相同的.revalidate属性(这未显示在上面的代码中(,再次免除文件在同一时间段的重新验证。

上面的函数似乎只从persistent_compile_file()调用,这是一个每当执行脚本时都会调用的函数。我找不到任何其他指示使用了另一个触发器的引用,例如计时器。

所以,来自 PHP 手册

检查脚本时间戳以获取更新的频率(以秒为单位(。 0 将导致 OPcache 检查每个请求的更新。

因此,正在

发生的事情是你正在更新文件,但你的指令说,从你更新文件到opcache构建新操作码的时间之间最多需要60秒。

validate_timestamps有答案。因为您要手动重新验证文件,所以可以执行此操作

禁用此指令时,必须通过 opcache_reset((、opcache_invalidate(( 或重新启动 Web 服务器手动重置 OPcache,以使对文件系统的更改生效。