今天下了spawn-fcgi的源码,花了点时间,终于明白线上2400个php-cgi的由来了,给大家分享下。
常用的lighttpd+fastcgi的配置有以下几个关键参数:(我们线上在/home/work/local/lighttpd/bin/fastcgi_control里都有对应,下面这个可能更容易理解)
fastcgi.server = ( ".php" =>
(( "socket" => "/tmp/php-fastcgi.socket",
"bin-path" => "/usr/bin/php-cgi",
"max-procs" => 10,
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "16",
"PHP_FCGI_MAX_REQUESTS" => "1000"
),
"broken-scriptfilename" => "enable"
))
)
其中,PHP_FCGI_MAX_REQUESTS的作用是在一个子进程工作一定次数后就干掉它,以免可能出现的问题连累系统,主进程会再创建一个相应的子进程来替补,保证子进程数一直是PHP_FCGI_CHILDREN个。
具体进程数是多少呢?有两个设置选项至关重要,分别是max-procs和PHP_FCGI_CHILDREN。如上所示的配置,系统将创建170个PHP-cgi的进程,它的计算公式如下:
num-procs = max-procs * ( 1 + PHP_FCGI_CHILDREN )
如果一个php-cgi进程占用十几兆内存的话,那么总计大约就要占用2G左右的内存。
我们先来看看max-procs的意思:从字面意思看,它似乎指得是最大进程数。实际它指的是Lighttpd一开始spawn多少个进程。
至于PHP_FCGI_CHILDREN的意思,和字面意思相同,指的就是每个主进程里产生多少个PHPFCGI子进程。
如果你的Lighttpd已经启动,你可以尝试执行一下命令:ps aux | grep php-cgi,将会看到大量的php-cgi进程:
nobody 10939 0.0 0.1 15556 4820 ? Ss 16:24 0:00 /usr/local/bin/php-cgi
nobody 11380 0.0 0.1 15452 5588 ? S 16:24 0:00 /usr/local/bin/php-cgi
仔细观察,你会发现这些php-cgi的状态不尽相同,有的是Ss,有的是S,通过man ps你能找到这些状态的含义:
S Interruptible sleep (waiting for an event to complete)
s is a session leader
也就是说,Ss状态的进程都是主进程(max-procs代表的那些进程),而S状态的进程都是子进程(PHP_FCGI_CHILDREN代表的那些进程)。如果不相信,你可以使用命令核实一下数量:
ps aux | grep php-cgi | grep Ss | grep -v grep | wc -l
确认了这些,我们再仔细看ps aux | grep php-cgi的结果,你还会发现主进程的内存占用(4840)和子进程的内存占用(5588)是不同的。这是因为主进程不处理实际的PHP请求,它唯一 的工作就是看管好自己手下的子进程。而实际的PHP请求都是由子进程来完成的,所以子进程占用的内存要稍大一些。
如此,我们对max-procs和PHP_FCGI_CHILDREN的含义应该理解了吧,那么对应我们线上的配置,max-procs是通过
spawn-fcgi –F 400
设置的,亦即进程数为400,而PHP_FCGI_CHILDREN这个值可以通过
spawn-fcgi –C xxx
来设置,线上使用的
引用
默认值,为5
。所以线上的总进程数为400*(1+5)=2400.
需要注意的是,我们线上使用的
引用
spawn-fcgi是1.5.0的版本,PHP_FCGI_CHILDREN的默认值是5;但我自己的开发机上使用的1.6.3的版本,PHP_FCGI_CHILDREN的默认值是0,即每个主进程直接处理php请求,不交由子进程处理
。
以下部分来自网上,仅供参考
还有一个问题:既然php-cgi的总进程数可以由上面的公式算出来,那么以下几个配置选项哪个好?
"max-procs" => 1,
"PHP_FCGI_CHILDREN" => "169",
"max-procs" => 2,
"PHP_FCGI_CHILDREN" => "84",
"max-procs" => 10,
"PHP_FCGI_CHILDREN" => "16",
以上三种配置产生的总进程数一样(都是170),我们如何判断配置的好坏呢?
如果使用了eAccelerator之类的PHP优化器,那么eAccelerator会为每一个主进程创建一个独立的缓存空间,这个时候如果你的 max-procs是2的话,就会建立两个独立的缓存空间。一方面这浪费了一些内存,另一方面如果你的一个主进程挂了(它下面的子进程就失控了),至少你还有一个主进程可以保持正常运转。
总体来说,max-procs不宜为较小,否则没有容错性,在有PHP优化器的时候也不宜过大,否则会浪费很多内存做缓存空间,即便没有装PHP优化 器,max-procs也不宜过大,因为主进程是不处理PHP请求的,过多的主进程自然就是一种浪费。确定了max-procs的值,剩下 PHP_FCGI_CHILDREN的值就好说了。
另外:通过命令
netstat -anp | grep php-cgi | wc -l
可以得知当前有多少php-cgi处于连接状态,如果接近php-cgi的总进程数,就说明应该加大进程数了