Nginx下php-fpm引起的502 Bad Gateway解决办法

上一篇文章,在让 Brust 客服解决 Network error 其间网站挂了,然后莫名地发现我的 php 不见了,很大的可能是 Brust 的客服不知运行了命令,把我的 php 给卸掉了,因为在让他们解决问题前一切都还是好的(这才是我博客挂了两天的原因)。由此可见,免费客服技术,真不能依赖。

自已尝试编译安装了几次都没成功,手动编译真的很麻烦!幸好在 Kevin125 的帮助下完装好了,其后自己补上了 pdo_mysql 模块和 memcached 模块。

重新安装好的 PHP 后,就算我把配置改成了在《Nginx 优于Apache与php-cgi进程僵死》的那样,依然会出现 502 Bad Gateway的错误,继续搜索,有了新的收获。

首先用查看php-cgi进程数:

 netstat -anpo | grep "php-cgi" |wc -l

得出来的值最高是35,一般18,这远远高于我在php-fpm.conf里设的max_children 值 8 !!

查看php-cgi程序:

 netstat -anpo | grep "php-cgi"

结果显示了一大堆 php-cgi 程序,其中有7、8个进程是服 Memcached 服务的,这让我非常地纠结,说明我在配置 php-fpm.config 里的数值都是无效的。经过搜索,发现我忽略了一个重要的细节:

目前最新5.3.x的php-fpm,有两种管理进程的方式,分别是static和dynamic。5.2.x的则是static 和 apache-like。

如果设置成static,进程数自始至终都是pm.max_children指定的数量,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers配置将没有作用。

如果设置成dynamic(apach_lick),则进程数是动态的,最开始是pm.start_servers指定的数量,如果请求较多,则会自动增加,但不超过pm.max_children指定的数量,同时保证空闲的进程数不小于pm.min_spare_servers,如果进程数较多,也会进行相应清理,保证多余的进程数不多于pm.max_spare_servers。

系统会在php-fpm运行开始 的时候启动pm.start_servers个php-fpm进程,
然后根据系统的需求动态在pm.min_spare_servers和 pm.max_spare_servers之间调整php-fpm进程数。

更多可查看《php-fpm导致CPU100%》

我一直都在设Max_children,却忘记了选择模式!!

其后,我再查看了php-fpm的log日志。关键几个错误有以下几个:

cat /usr/local/php/logs/php-fpm.log
May 06 12:04:39.284106 [WARNING] fpm_request_check_timed_out(), line 158: child 18312, script '/home/wwwroot/duyuxian/index.php' (pool default) execution timed out (5.109937 sec), terminating
May 06 12:04:39.596200 [WARNING] fpm_children_bury(), line 215: child 18312 (pool default) exited on signal 15 SIGTERM after 937.741270 seconds from start

May 06 13:36:03.403271 [NOTICE] fpm_pctl_kill_all(), line 181: 8 children are st ill alive
May 06 13:36:03.371129 [NOTICE] fpm_pctl_kill_all(), line 172: sending signal 15 SIGTERM to child 24321 (pool default)
May 06 11:49:01.852645 [NOTICE] fpm_children_make(), line 352: child 18310 (pool default) started
May 07 13:53:13.679846 [NOTICE] fpm_got_signal(), line 48: received SIGCHLD

这些错误只有前两面个会让 PHP 挂了,其余的都是警告,第一条是请求超时,我之前设的是5s。

第二条我猜是 php-cgi 进程高达 15 后就挂了。

第三条和第四条,我猜是 Max_children 的设置警告,前面是说关闭得只剩8个,后者是半闭得只剩 15  个。

最后两条就真猜不到了。

于是,我重新地设置了一下我的 php-cgi 进程,直接看代码。

我把最长的请求时间 request_terminate_timeout 从 5s 改到了300s, 把 max_request 从1024改到了700(一个php-cgi能处理700次请求对于我的博客来说绰绰有余),把模式全改成了apache-like,max_children 还是8,min_spare_servers 是 8,max_spare_servers 是15。 request_slowlog_timeout 为 20s。

Sets style of controling worker process count.
Valid values are 'static' and 'apache-like'
apache-like
 Sets the limit on the number of simultaneous requests that will be served.
Equivalent to Apache MaxClients directive.
 Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi
Used with any pm_style.
8
Settings group for 'apache-like' pm style

Sets the number of server processes created on startup.
Used only when 'apache-like' pm_style is selected
8
Sets the desired minimum number of idle server processes.
Used only when 'apache-like' pm_style is selected
5
Sets the desired maximum number of idle server processes.
Used only when 'apache-like' pm_style is selected
15

The timeout (in seconds) for serving a single request after which the worker process will be terminated
Should be used when 'max_execution_time' ini option does not stop script execution for some reason '0s' means 'off'
300s
The timeout (in seconds) for serving of single request after which a php backtrace will be dumped to slow.log file '0s' means 'off'
20s
The log file for slow requests
logs/slow.log
Set open file desc rlimit
51200
 Set max core size rlimit

在重启php-fpm之前,最好关闭所有的php-cgi以释放内存,因为单单重启php-fpm是无法释放内存的。

killall php-cgi
/usr/local/php/sbin/php-fpm restart

再查看php-cgi程序:

 netstat -anpo | grep "php-cgi"

还是超过了我的预设置,其中有很多是 memcached 的,我现在还在考虑到底要不要把 Memcached 关闭了,似乎关闭了依然还是很多 php-cgi 进程,而且内存并没有降多少。不过,我已经没折了。

最后,为了防止网站502错误发生,我网上弄了一个检测脚本,如有 502 错误就自行重启 php-fpm 每隔两分钟查一次。

脚本如下:

	#!/bin/bash
	MY_URL="http://www.duyuxian.info/"
	RESULT=`curl -I $MY_URL|grep "HTTP/1.1 502"`
	if [ -n "$RESULT" ]; then
	/usr/local/php/sbin/php-fpm restart
	fi

将其加入cronjob

Crontab -e

然后I (Insert)

*/2 * * * * /root/php502.sh

ESC 然后 :wq! 保存退出。

你可以使用

 cat /var/log/cron

检查执行情况,但其实还是知道不了是否effective,除非你网站502过。

最后,我还是把系统文件最大并发数改成了51200.

cat /etc/sysctl.conf
 fs.file-max=51200

设置完这一切,VPS 的内存使用还是高达 70% 左右(因为我一共就四个网站,两个建站程序,严格来说只有一个网站是有流量的),但这是比较优的使用率的了,我又不是什么极客,不会非得挑战用 64M 跑 WordPress,而php-cgi进程都是待命的,启动了后平常的流量读取数据不会再提高多少内存使用率的了。如果能保持这种状态一直运行是不错的。

有人建议把PHP的运行模式从 Fastcgi 改成 spawn-fcgi ,应该挺好使的吧,但我没有去弄,因为太闹腾了。从中午到现在,log 日志没有再显示有什么警告和错误,如果再还有的话,估计我就会试着使用 spawn-fcgi 。

加入对话

4条评论

  1. php5.2.x的apache-like模式并没有实现,可以查看php-fpm的源代码得知,所以5.2.x下面只能用静态模式,根据内存合理设置吧~~wd的话加静态化插件吧 [洋葱头22]

留下评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据