服务器环境:redhat linux 5.5 , nginx , phpfastcgiphp
在此环境下,通常php-cgi运行是很是稳定的,但也遇到过php-cgi占用太多cpu资源而致使服务器响应过慢,我所遇到的php-cgi进程占用cpu资源过多的缘由有:linux
1. 一些php的扩展与php版本兼容存在问题,实践证实 eAccelerater与某些php版本兼容存在问题,具体表现时启动php-cgi进程后,运行10多分钟,奇慢无比,但静态资源访问很快,服务器负载也很正常(说明nginx没有问题,而是php-cgi进程的问题),解决办法就是从php.ini中禁止掉eAccelerater模块,再重启php-cgi进程便可nginx
2. 程序中可能存在死循环,致使服务器负载超高(使用top指令查看负载高达100+), 须要借助Linux的proc虚拟文件系统找到具体的问题程序shell
3. php程序不合理使用session , 这个发生在开源微博记事狗程序上,具体表现是有少许php-cgi进程(不超过10个)的cpu使用率达98%以上, 服务器负载在4-8之间,这个问题的解决,仍然须要借助Linux的proc文件系统找出缘由。bash
4. 程序中存在过分耗时且不可能完成的操做(仍是程序的问题),例如discuz x 1.5的附件下载功能: source/module/forum/forum_attachement.php中的定义服务器
function getremotefile($file) {
global $_G;
@set_time_limit(0);
if(!@readfile($_G['setting']['ftp']['attachurl'].'forum/'.$file)) {
$ftp = ftpcmd('object');
$tmpfile = @tempnam($_G['setting']['attachdir'], '');
if($ftp->ftp_get($tmpfile, 'forum/'.$file, FTP_BINARY)) {
@readfile($tmpfile);
@unlink($tmpfile);
} else {
@unlink($tmpfile);
return FALSE;
}
}
return TRUE;
}cookie
没有对传入的参数做任何初步检查,并且设置了永不超时,而且使用readfile一次读取超大文件,就可能存在如下问题:
A. 以http方式读取远程附件过分耗时session
B. FTP没法链接时,如何及时反馈出错误?优化
C. readfile是一次性读取文件加载到内存中并输出,当文件过大时,内存消耗惊人网站
根据实验发现采用readfile一次性读取,内存消耗会明显增长,可是CPU的利用率会降低较多。若是采用分段读取的方式,内存消耗会稍微降低,而CPU占用却会明显上升。
对discuz x 1.5的这个bug较好解决方法就是后台从新正确设置远程附件参数。
如下是我逐步整理的故障排除步骤:
1. 获得占用cpu资源过多的php-cgi进程的pid(进程id), 使用top命令便可,以下图:
通过上图,咱们发现,有两个php-cgi进程的cpu资源占用率太高,pid分别是10059,11570,这通常都是程序优化不够形成,如何定位问题的php程序位置?
2. 找出进程所使用的文件
/proc/文件系统保存在内存中,主要保存系统的状态,关键配置等等,而/proc/目录下有不少数字目录,就是进程的相关信息,以下图,咱们看看进程10059正在使用哪些文件?
显然,使用了/home/tmp/sess_*文件,这明显是PHP的session文件, 咱们查看这个session文件的内容为:view_time|123333312412
到这里,咱们已经能够怀疑是因为php程序写入一个叫view_time的session项而引发, 那么剩余的事件就是检查包含view_time的全部php文件,而后修改之(好比改用COOKIE),这实话, 这个view_time并不是敏感数据,仅仅记录用户最后访问时间,实在不必使用代价巨大的session, 而应该使用cookie。
3. 找出有问题的程序,3002065622修改之
使用vi编辑如下shell程序(假设网站程序位于/www目录下)
#!/bin/bash
find /www/ -name "*.php" > list.txt
f=`cat ./list.txt`
for n in $f
do
r=`egrep 'view_time' $n`
if [ ! "$r" = "" ] ; then
echo $n
fi
done
运行这个shell程序,将输出包含有view_time的文件, 对记事狗微博系统,产生的问题位于modules/topic.mod.class文件中