在此之前/其他地方已经提出道歉,但我找不到答案。
我们在部署后的一分钟内遇到了一些问题,我们认为它们与Opcache有关。在我们的实时设置中,我们有以下Opcache设置:
opcache.revalidate_freq=60
opcache.validate_timestamps=1
PHP做了以下哪些操作?
当PHP需要一个文件时,在那一点检查它是否自上次生成文件的新缓存以来已经过60秒,如果它已经更多,那么为此请求生成一个新缓存? / p>
或者它是否在某种形式的计时器(或其他)上运行,其中60秒与上次需要文件无关?
我期待选项1,但这不能解释我们60秒左右的问题,因为文件的文件路径不同,因为我们每次都部署到交替的A或B目录。
我希望这有道理吗?谢谢你的帮助。
答案 0 :(得分:3)
根据我对PHP源代码的分析,会发生与选项1类似的事情。当PHP需要文件时,它检查自上次编译或重新验证文件以来是否opcache.revalidate_freq
秒。如果没有,它将跳过重新验证(时间戳检查)。
换句话说,opcache.revalidate_freq
设置指定时间戳检查的最大频率。 文件直到被请求后才会重新验证,即使距上次重新验证已经一年了。
这是ZendAccelerator.c中的C function,用于处理缓存验证:
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检查文件的时间戳,并发现自将文件放入缓存以来,该文件没有更改时,它将为另一个{{ 1}}秒(opcache.revalidate_freq
属性)。这样可以避免在该时间段内进行进一步的时间戳检查(PHP将假定文件是最新的)。
如果重新验证不成功–即时间戳比缓存中的时间戳新,则将导致重新编译,这还将设置相同的.revalidate
属性(以上代码中未显示),再次免除重新验证同一时间段的文件。
似乎仅从persistent_compile_file()
调用了上述函数,该函数在执行脚本时都会被调用。我找不到任何其他引用,表明使用了另一个触发器,例如计时器。
答案 1 :(得分:1)
所以,来自PHP manual
检查脚本时间戳的更新频率,以秒为单位。 0将导致OPcache检查每个请求的更新。
所以正在发生的是你正在更新文件,但是你的指令说你在更新文件和opcache构建新操作码之间的时间长达60秒。
validate_timestamps 有答案。因为您想手动重新验证文件,所以可以执行此操作
禁用此指令时,必须通过opcache_reset(),opcache_invalidate()手动重置OPcache,或者重新启动Web服务器以使文件系统的更改生效。