现在的位置:首页>空间域名>正文

linux下php-cgi或php-fpm进程占用cpu,内存资源高的一个解决实例

2016年06月19日 ⁄ 共 2606字 评论 2 条

一般来说,只要您的linux系统出现占用CPU资源高,或者占用内存多的放,都离不开php-cgi或php-fpm进程,当然,还有一个进程就是mysqld进程,遇到这样的问题,如果对linux系统不是很熟悉的话,是相当头痛的.福利老幺前一段时间就出现过一次,到现在还没有完美解决,所以先收集一些这样的解决案例,下次备查,当然,相信还是有朋友能用得上的.

一起来看看这个案例:

服务器环境:redhat linux 5.5 , nginx , phpfastcgi

在此环境下,一般php-cgi运行是非常稳定的,但也遇到过php-cgi占用太多cpu资源而导致服务器响应过慢,我所遇到的php-cgi进程占用cpu资源过多的主要原因有如下几个:

1. 一些php的扩展与php版本兼容存在问题,实践证明 eAccelerater与某些php版本兼容存在问题,具体表现时启动php-cgi进程后,运行10多分钟,奇慢无比,但静态资源访问很快,服务器负载也很正常(说明nginx没有问题,而是php-cgi进程的问题),解决办法就是从php.ini中禁止掉eAccelerater模块,再重启php-cgi进程即可.这一个一般来说是比如好解决的.

2. 程序中可能存在死循环,导致服务器负载超高(使用top指令查看负载高达100+), 需要借助Linux的proc虚拟文件系统找到具体的问题程序

3. php程序不合理使用session, 这个发生在开源微博记事狗程序上,具体表现是有少量php-cgi进程(不超过10个)的cpu使用率达98%以上, 服务器负载在4-8之间,这个问题的解决,仍然需要借助Linux的proc文件系统找出原因.

4. 程序中存在过度耗时且不可能完成的操作(还是程序的问题),例如discuz x 1.5的附件下载功能:

source/module/forum/forum_attachement.php中的定义

  1. function getremotefile($file) {
  2.     global $_G;
  3.     @set_time_limit(0);
  4.     if([email protected]($_G['setting']['ftp']['attachurl'].'forum/'.$file)) {
  5.         $ftp = ftpcmd('object');
  6.         $tmpfile = @tempnam($_G['setting']['attachdir'], '');
  7.         if($ftp->ftp_get($tmpfile, 'forum/'.$file, FTP_BINARY)) {
  8.             @readfile($tmpfile);
  9.             @unlink($tmpfile);
  10.         } else {
  11.             @unlink($tmpfile);
  12.             return FALSE;
  13.         }
  14.     }
  15.     return TRUE;
  16. }

没有对传入的参数作任何初步检查,而且设置了永不超时,并且使用readfile一次读取超大文件,就可能存在以下问题:

1.. 以http方式读取远程附件过度耗时

2. FTP无法连接时,如何及时反馈出错误?

3. readfile是一次性读取文件加载到内存中并输出,当文件过大时,内存消耗惊人

根据实验发现采用readfile一次性读取,内存消耗会明显增加,但是CPU的利用率会下降较多。如果采用分段读取的方式,内存消耗会稍微下降,而CPU占用却会明显上升.

对discuz x 1.5的这个bug较好解决方法就是后台重新正确设置远程附件参数.

以下是我逐步整理的故障排除步骤:

1. 得到占用cpu资源过多的php-cgi进程的pid(进程id), 使用top命令即可,如下图:

top命令

经过上图,可以发现,有两个php-cgi进程的cpu资源占用率过高,pid分别是10059,11570,这一般都是程序优化不够造成,如何定位问题的php程序位置?

2. 找出占内存高的进程所使用的文件

/proc/文件系统保存在内存中,主要保存系统的状态,关键配置等等,而/proc/目录下有很多数字目录,就是进程的相关信息,如下图,我们看看进程10059正在使用哪些文件?

找出进程所使用的文件

补充一下,下面的这个命令,在查找原因是用得非常多,而且我们一般情况下,可以多试下这个命令.

  1. ll /proc/pid/fd/

显然,使用了/home/tmp/sess_*文件,这明显是PHP的session文件, 我们查看这个session文件的内容为:view_time|123333312412

到这里,我们已经可以怀疑是由于php程序写入一个叫view_time的session项而引起, 那么剩余的事件就是检查包含view_time的所有php文件,然后修改之(比如改用COOKIE),这实话, 这个view_time并非敏感数据,仅仅记录用户最后访问时间,实在没必要使用代价巨大的session, 而应该使用cookie.

3. 找出有问题的程序,修改之

使用vi编辑以下shell程序(假设网站程序位于/www目录下)

  1. #!/bin/bash
  2.  find /www/ -name "*.php" > list.txt
  3. f=`cat ./list.txt`
  4. for n in $f
  5. do
  6.     r=`egrep 'view_time' $n`
  7.     if [ ! "$r" = "" ] ; then
  8.         echo $n
  9.      fi
  10. done

运行这个shell程序,将输出包含有view_time的文件, 对记事狗微博系统,产生的问题位于modules/topic.mod.class文件中.

接下来就是处理这个文件了.

 

 

小结

文章内容来源自网络,由福利老幺整理发布.

一般的新手遇到这样的问题,如果您的wodpress博客或者discuz论坛,可以先停用一些插件,最好全部停掉,然后套用官方的标配模板再来处理这些问题.

评论 2 条 评论内容很精采,有内幕,而且绝对有干货

  1. 阿勇 2016年08月15日 00:56  @回复  Δ-49楼 回复

    被攻击 php-fpm 进程太多导致502 top命令查看只有mysqlcpu使用率太高 有办法缓解或者阻止这样的攻击吗


    • 管理员
      管理员 2016年08月15日 07:40  @回复  ∇地下1层 回复

      先要找出对应的进程才能查看具体是在执行何种操作。

给我留言