Nginx 优于Apache与php-cgi进程僵死

关于Nginx与Apache,之前有说过,但星期六早上发现偶尔还是会出现502 Bad gateway 错误,不得不再认真研究一下.。

这次我很认真地看了张宴的优化方案。先看看《 Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器(第6版)》  里Nginx与Apache的比较:

 Nginx性能比Apache高得多得益于Nginx使用了最新的epoll(Linux 2.6内核)和kqueue(freebsd)网络I/O模型,而Apache则使用的是传统的select模型。目前Linux下能够承受高并发访问的Squid、Memcached都采用的是epoll网络I/O模型。

处理大量的连接的读写,Apache所采用的select网络I/O模型非常低效。下面用一个比喻来解析Apache采用的select模型和Nginx采用的epoll模型进行之间的区别:

假设你在大学读书,住的宿舍楼有很多间房间,你的朋友要来找你。select版宿管大妈就会带着你的朋友挨个房间去找,直到找到你为止。而epoll版宿管大妈会先记下每位同学的房间号,你的朋友来时,只需告诉你的朋友你住在哪个房间即可,不用亲自带着你的朋友满大楼找人。如果来了10000个人,都要找自己住这栋楼的同学时,select版和epoll版宿管大妈,谁的效率更高,不言自明。同理,在高并发服务器中,轮询I/O是最耗时间的操作之一,select和epoll的性能谁的性能更高,同样十分明了。


 

好了,以下与以上无关。

Nginx的502 Bad gateway的错误其实很容易猜到是php-fpm 挂了。

先是使用

cat /usr/local/nginx/logs/error.log

cat /usr/local/php/logs/php-fpm.log

查看错误信息。

Nginx没有问题,的确是php-fpm的问题。

 Apr 29 20:49:08.237827 [NOTICE] fpm_children_make(),
line 352: child 22350 (pool default) started

显然是php-cgi进程数不够用、php执行时间长或者是php-cgi进程死掉,导致了502错误。

解决这些问题不能只看网上的设置,因为每个人的主机情况都是不同的,关键要学会如何设数值。

1、10个Nginx进程消耗150M内存(15M*10=150M),开启的64个php-cgi进程消耗1280M内存(20M*64=1280M),即一个php-cgi约消耗20M内存。

2、PHP(FastCGI)模式适用于执行时间较短的PHP程序,一般复杂的PHP程序执行时间应该在100ms以内。假设一个PHP程序的执行时间为100ms,那么一个PHP(FastCGI)进程每秒可以处理完毕10个请求。在生产环境下,PHP(FastCGI)模式还受到内存、系统负载等多方面的影响, 因此FastCGI的进程不是越多越好,而是够用就好。

3、php-fpm消耗的内存是由max_requests的值(该值的意思是发送多少个请求后会重启该线程,)与max_children(每次php-fpm会建立多少个进程)相乘所得出的。如果要降低内存,就是降低这两个值。但把max_requests设得太小了,进程数有可能很快就不够用,然后502。如果max_children设小了,就会出现等待时间长,一样会502。这些值当越大越好,内存消耗当然也越大,但你的主机有条件么?所以我们要根据我们的主机和网站请求数去设置这些值。

1、查看当前的PHP FastCGI进程数是否够用:

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

如果得出的值近似于max_children的置,那么说明,进程数的值设得太小了,要增大。

2、部分 PHP 程序的执行时间超过了 Nginx 的等待时间,可以适当增加 nginx.conf 配置文件中 FastCGI 的 timeout 时间,例如:

http{......

fastcgi_connect_timeout 300;

fastcgi_send_timeout 300;

fastcgi_read_timeout 300;

......}

3、在php-fpm.conf设置中还有一项max_execution_time,就是fast-cgi的执行脚本时间。

0s为关闭,让PHP-CGI一直执行下去而没有时间限制。优化fastcgi,可以增大这个值。一般来说性能越好你可以设置越高。

好了,总结了那么多,开始设置我的主机:

1、 Usr /local/php/etc/php-fpm.conf  设置php-cgi进程数

8

我的主机内存512,把max_children设成8的话,将消耗160M的内存(8*20M=160M),这个值是安全的。

然后把 max_execution_time ,设为5s

5s

2、Usr /local/nginx/conf/nginx.conf  设置 Nginx 的进程数  worker_processes 3;  这个将消耗75M内存(3*15M=75M )

同时把fastcgi的处理时间变长:

fastcgi_connect_timeout 320;

fastcgi_send_timeout 320;

fastcgi_read_timeout 320;

3、还有一种情况,要查看以下两处的值是否一样。

Php-fpm.conf

/tmp/php-cgi.sock

nginx.conf

fastcgi_pass unix:/tmp/php-cgi.sock;

4、网上还指出 rlimit_files 的值要保持一致。

使用

ulimit -n

查看文件最大连接值。

默认的话 nginx.conf  的值是 worker_rlimit_nofile 51200;

php-fpm.conf  的值也是  51200,

51200

唯一系统内核的设置不一样,

cat /etc/sysctl.conf

会发现

 fs.file-max=65535

65535大于51200,其实是没有修改的必要的。

 

设置完毕后,我的内存飙升到了接近400M,约75%使用率,有些汗了,不过还能Hold住,不要再增回就好,关键是希望从此以后不要再出现502 Bad gateway错误了。

 

PS:如果你不小心看到了这篇文章,建议你再看看这篇文章:《Nginx下php-fpm引起的502 Bad Gateway解决办法》

 

加入对话

7条评论

  1. 刚换成lnmp,老是有502错误,按博主的方法改了一下,warning信息没了,但还是有超时的notice出现,真郁闷...

    原来用lnmpa就没这个问题

  2. @昂羽
    Notice没什么关系,不会影响使用。
    另外你用了LNMPA,就是多用了个Apache,用Apache处理PHP等动态文件。你的服务器要多运行一个程序,负重大了那么一点点。不过你能正常使用就好。

  3. 支持下,现在还出现那个问题吗?
    php-fpm.conf中是否需要增加如下参数,以终止php脚本执行时间在2分钟以上的:
    request_terminate_timeout = 120s

留下评论

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

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