Internet有很多讨论,认为在CLI中调用apc_cache_clear()
并不能从"web"PHP进程中清除操作码缓存,无论它们是在Apache内部运行还是由FPM运行(请参阅如何清除APC缓存项?)。作为一个建议的解决方案,可以创建一个调用apc_cache_clear()
的简单PHP页面,并从CLI中调用它。Symfony的ApcBundle做到了这一点。
如果CLI中的apc_cache_clear()
没有清空Apache/FPM中的缓存,那么它是否在FPM工作程序之间?如果我通过HTTP调用/clearApc_cache.php,它只由一个FPM工作进程运行。那么,APC操作码缓存真的在池和工作程序之间共享吗?更具体地说:它会自动从所有工作程序中清除吗?
所有php fpm工作进程与父php fpm进程共享相同的操作码缓存;来源如果您有一个/apc_clear_check.php文件,并且您通过HTTP调用它(使用类似curl的东西),那么您将使用相同的php-fpm主进程清除所有工作程序的操作码缓存。
这篇博客文章很好地解释了apc是如何工作的,以及如何在发布期间有效地清除它。
如果直接通过FastCGI接口执行脚本,您可以通过cli清除操作码缓存,而无需将文件部署到您的网站。
我已经创建了这个要点,您可以在服务器上使用它来清除php5-fpm缓存。
如果您使用的是unix套接字:
php clear-apc.php --sock /var/run/php5-fpm.sock
否则:
php clear-apc.php --port=[port]
或忽略默认127.0.0.1:9000
我刚刚发现不同的池也共享相同的APC缓存,至少在带有FPM的PHP 5.4中是这样,就操作码缓存内容而言也是如此。
我就是这样注意到的:
我已经设置了多个PHP-FPM池,每个池都记录在/srv/www/domain.com/目录下。
PHP脚本的主要位置是/srv/www/domain.com/docroot/.
现在,如果我创建一个文件/srv/www/domain_1.com/docroot/test.php,并加载脚本,它将显示它应该显示的内容。
但是,当我创建文件/srv/www/domain_2.com/docroot/test.php时,内容也显示在domain_1.com下。
我认为发生这种情况是因为APC使用文件位置作为其缓存的密钥,在这两种情况下,密钥都是/docroot/test.php。
清除操作码缓存可能仅限于单个池。不过我还没有测试过。
EDIT清除操作码缓存不会重新限制到单个应用程序池,当调用APC_cache_clear()时,会清除整个APC缓存。
我还尝试使用apc.mmap_file_mask为每个池指定不同的掩码。这并没有改变任何事情,一个应用程序池中的更新文件在其他池中可见。
在apc.stat=0设置时观察到了这种行为。对文件的所有更改都使用lsyncd进行监控,从而强制重新编译APC缓存中的条目。
- Tero