我在切罗基1.2.101上的FastCGI中运行Archlinux/php-fpm 5.3.9的一些服务器上遇到了间歇性问题。我正在使用一个缓存插件,它使用以下逻辑构建并提供静态缓存文件:
$cache_file = md5($host . $uri) . '.cache';
if( file_exists($cache_file) ) {
$cache_file_contents = file_get_contents($cache_file)
exit( $cache_file_contents );
}
// else build/save the $cache_file
一些进程最终会出现在挂在exit()
调用上的php-fpm的慢速日志中。当负载达到峰值时,100%的CPU使用率(几乎)完全转移到Web服务器,PHP页面开始返回500-内部服务器错误。有时服务器自己恢复,其他的我需要重新启动php-fpm和cherokee。
我已将PHP-FPM的FastCGI设置配置为执行
即使这是一个VPS,我也会暂时排除文件系统上的IO等待,因为缓存文件应该已经加载了。我还没能在用
vmstat
测试的过程中捕捉到它我将
pm.max_requests
设置为500,但不知道exit()
调用是否会干扰进程的循环。php-fpm日志显示了很多
WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)
。这似乎是php-fpm通过调节池中子进程数量的正常部分
任何有关故障排除的提示都将不胜感激。以下是我发现的引起一些危险信号的3件事:
http://www.php.net/manual/en/function.exit.php#96930
https://serverfault.com/questions/84962/php-via-fastcgi-terminated-by-calling-exit#85008
为fastCGI调用exit()函数时出错?
这可能与将输出传递到服务器(也跟踪I/O)有关。您可以通过让您的Web服务器为静态缓存文件提供服务来避免FPM。除此之外,我建议您使用这个PHP块来减少一点内存/I/O:
if (file_exists($cache_file))
{
readfile($cache_file)
exit;
}
参见readfile
。
如果你不想使用exit
(我个人从未遇到过在PHP中使用FastCGI的问题),你应该清理你的代码,这样就没有必要使用exit,例如你可以使用return
或查看你的代码流,为什么你需要使用exit并消除问题。
我最终使用了Pythonic Exception包装方法,该方法在http://www.php.net/manual/en/function.exit.php
在主索引.php中
class SystemExit extends Exception {}
try{
/* Resume loading web-app */
}
catch (SystemExit $e) {}
在问题的缓存逻辑中,替换exit( $cache_file_contents );
while (@ob_end_flush());
flush();
echo $cache_file_contents;
throw new SystemExit();
这缓解了显示挂在exit()
上的php-fpm慢速日志。我不完全相信它解决了根本问题,但它已经清理了日志文件。