nginx系统占用CPU过高

一般来说,只要您的linux系统出现占用CPU资源高,或者占用内存多的放,都离不开php-cgi或php-fpm进程,当然,还有一个进程就是mysqld进程,遇到这样的问题,如果对linux系统不是很熟悉的话,是相当头痛的

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

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

eAccelerator 组件不知什么原因占用 CPU 过高,打开 php.ini
vi /usr/local/php/etc/php.ini
删除 eAccelerator 的配置信息,重启 lnmp
/root/lnmp restart
但还是没有彻底解决问题,几个小时后,我又重启了 lnmp ,居然发现,似乎已经越来越平稳啦。
可能用到的命令:

top //查看CPU、内存使用信息,查看哪个进程占用CPU高以及它的PID
ll /proc/PID号/fd/ // 通过PID找到哪个文件操作的进程,进而知道问题所在
https://www.jb51.net/article/92978.htm

可能存在的原因2:
参数配置不当

php-fpm优化方法
php-fpm存在两种方式,一种是直接开启指定数量的php-fpm进程,不再增加或者减少;
另一种则是开始时开启一定数量的php-fpm进程,当请求量变大时,动态的增加php-fpm进程数到上限,当空闲时自动释放空闲的进程数到一个下限。
这两种不同的执行方式,可以根据服务器的实际需求来进行调整。

要用到的一些参数,分别是pm、pm.max_children、pm.start_servers、pm.min_spare_servers和pm.max_spare_servers。

pm表示使用那种方式,有两个值可以选择,就是static(静态)或者dynamic(动态)。

下面4个参数的意思分别为:

pm.max_children:静态方式下开启的php-fpm进程数量,在动态方式下他限定php-fpm的最大进程数(这里要注意pm.max_spare_servers的值只能小于等于pm.max_children)
pm.start_servers:动态方式下的起始php-fpm进程数量。
pm.min_spare_servers:动态方式空闲状态下的最小php-fpm进程数量。
pm.max_spare_servers:动态方式空闲状态下的最大php-fpm进程数量。
如果dm设置为static,那么其实只有pm.max_children这个参数生效。系统会开启设置的数量个php-fpm进程。

如果dm设置为dynamic,4个参数都生效。系统会在php-fpm运行开始时启动pm.start_servers个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数。

那么,对于服务器,选择哪种执行方式比较好呢?事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始时一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。(www. 脚本学堂)

所以,动态方式因为会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或者VPS上使用。具体最大数量根据 内存/20M 得到。
比如说512M的VPS,建议pm.max_spare_servers设置为20(512*0.8/20)。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。

然后对于比较大内存的服务器来说,设置为静态的话会提高效率。
因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到。
比如说2GB内存的服务器,可以设置为50;4GB内存可以设置为100等。

对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到,比如8GB内存可以设置为100,那么php-fpm耗费的内存就能控制在 2G-3G的样子。如果内存稍微小点,比如1G,那么指定静态的进程数量更加有利于服务器的稳定。这样可以保证php-fpm只获取够用的内存,将不多的内存分配给其他应用去使用,会使系统的运行更加畅通。
对于小内存的服务器来说,比如256M内存的VPS,即使按照一个20M的内存量来算,10个php-cgi进程就将耗掉200M内存,那系统的崩溃就应该很正常了。因此应该尽量地控制php-fpm进程的数量,大体明确其他应用占用的内存后,给它指定一个静态的小数量,会让系统更加平稳一些。或者使用动态方式,因为动态方式会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或VPS上使用。具体最大数量根据 内存/20M 得到。比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。
https://www.jb51.net/article/92982.htm

比如,如果是512M的vps,设置的参数如下:

代码示例:
pm=dynamic
pm.max_children=20
pm.start_servers=5
pm.min_spare_servers=5
pm.max_spare_servers=20
可以最大的节省内存并提高执行效率。

PS.
pm.min_spare_servers、pm.max_spare_servers这2个参数一开始我以为是指空闲进程,但是后来服务器给我报了一个错误:
pm.start_servers(70) must not be less than pm.min_spare_servers(15) and not greater than pm.max_spare_servers(60)
要求pm.start_servers的值在pm.min_spare_servers和pm.max_spare_servers之间,经过测试,得出上述结论。
http://blog.itpub.net/14184018/viewspace-1797411/
https://blog.csdn.net/wangschang/article/details/38540617

可能存在的原因3:

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

可能存在的原因4:

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

可能存在的原因5:

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

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

function getremotefile($file) {
global $_G;br/>@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)) {
br/>@readfile($tmpfile);
@unlink($tmpfile);
} else {
br/>@unlink($tmpfile);
return FALSE;
}
}
return TRUE;
}
没有对传入的参数作任何初步检查,而且设置了永不超时,并且使用readfile一次读取超大文件,就可能存在以下问题:

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

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

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

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

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

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

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

top命令

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

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

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

找出进程所使用的文件

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

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.

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

使用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文件中.

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

在免费部落的网站中,与linux下占用cpu,内存资源高相关的话题还有:

1.wordpress使用lnmp环境cpu占用高到100%的处理

2.LNMP Nginx环境下CPU某个时间段占用高的处理

3.阿里云VPS下LNMP cpu 100% mysqld和php-fpm占内存的解决方法

小结

php-fpm目前主要又两个分支,分别对应于php-5.2.x的版本和php-5.3.x的版本。在5.2.x的版本中,php-fpm.conf使用的是xml格式,而在新的5.3.x版本中,则是和php.ini一样的配置风格。
在5.2.x版本中,php-fpm.conf中对于进程管理号称是有两种风格,一种是静态(static)的,一种是类似于apache风格(apache-like)的。

参考地址:
http://www.mfbuluo.com/23122.html

猜你喜欢

转载自blog.51cto.com/firephoenix/2165562