Update: I've since moved to a PHP-FPM with mod_fastcgi
based setup which works
much better than mod_fcgid
could ever dream of, taking process management away
from Apache and putting it where it actually makes sense has improved server
load and improved website speed. See my new PHP-FPM
with mod_fastcgi post for more information.
--
Errors, all they cause is trouble. The dreaded 500 error showed up when
visiting my favourite tech website, the one I am the administrator for. This
time I had enough, there was going to be no more playing around with PHP
settings, attempting to figure out why PHP was suddenly dying and or why
mod_fastcgi
refused to retry a select() when it failed due to a system
signal.
The server in question runs Apache in MPM worker mode since a threaded Apache
is going to be faster than a pre-fork, besides this server does not have as
much memory so it seemed to be better to have multiple threads rather than
multiple processes, each of which would have their own memory segment. There
however is the issue that this server also needs to run PHP, the accepted
method to do so is to use mod_php
along with Apache; however PHP is not thread
safe.
The alternative is FastCGI, basically it spawns PHP processes as a separate
stand-alone process, with their own memory space, much like Apache pre-fork,
however now when one process grows to big, or when a process is no longer
needed it can be cleaned up, keeping memory to a minimum. Also, FastCGI is
perfectly thread safe, this means that with Apache running in MPM worker mode
we could now still run our PHP scripts even when they were not thread safe.
Setting up mod_fastcgi
is not that hard, it takes some httpd.conf
configuration values, and off course the loadmodule is assumed here:
# Set up mod_fastcgi
<IfModule `mod_fastcgi`.c>
FastCgiIpcDir /var/tmp/fcgi-ipc/
FastCgiConfig -autoUpdate -singleThreshold 100 -killInterval 300 -idle-timeout 240 -pass-header HTTP_AUTHORIZATION
AddHandler fastcgi-script .fcgi .fcg .fpl
Action application/x-httpd-php5 /fastcgi-bin/php5.fcgi
AddType application/x-httpd-php5 .php .php5
</IfModule>
# Set up the script alias, basically anything in this directory gets executed as a fastcgi script
ScriptAlias /fastcgi-bin/ "/usr/local/www/fastcgi-bin/"
<Location /fastcgi-bin/>
Options ExecCGI
SetHandler fastcgi-script
Order allow,deny
Allow from all
</Location>
Because of errors that mod_fastcgi
was throwing out at me, I figured
mod_fcgid
is worth a try. However all of the configurations I found required
me to add an FCGIWrapper line into each of my VirtualHost blocks, which was an
immediate no-no since there is well over 100 of those on the server, and I'd
rather spend my time doing other things.
With some trial and error, and some Googling I put the following together for
mod_fcgid
, tested it out, and once it worked perfectly set Apache off running
with the following configuration:
# Set up mod_fcgid
<IfModule `mod_fcgid`.c>
AddHandler fcgid-script .fcgi .fcg .fpl
IPCCommTimeout 60
SocketPath /var/tmp/fcgi-ipc/
Action application/x-httpd-php5 /fastcgi-bin/php5.fcgi
AddType application/x-httpd-php5 .php .php5
</IfModule>
# Set up the script alias, basically anything in this directory gets executed as a fastcgi script
ScriptAlias /fastcgi-bin/ "/usr/local/www/fastcgi-bin/"
<Location /fastcgi-bin/>
Options ExecCGI
SetHandler fcgid-script
Order allow,deny
Allow from all
</Location>
Notice how similar they both are, that was the whole goal. mod_fcgid
was
supposed to be a drop in replacement, and thankfully it was. PHP was served as
it once was, with a twist.
The php5.fcgi script is as follows for those of you trying to set this up as
well:
| #!/bin/sh
# To use your own php.ini, comment the next line and uncomment the following one
#PHPRC="/usr/local/etc"
#export PHPRC
PHP_FCGI_CHILDREN=4
export PHP_FCGI_CHILDREN
exec /usr/local/bin/php-cgi
|
Some things that that intrigued me is that my php processes seemed to be capped
now. Where mod_fastcgi
would spawn processes but never remove them or kill
them when they were no longer needed, mod_fcgid
keeps the running php
processes to a sane limit instantly starting new processes when required to
handle the requests coming in. This means that the server now has more free
memory for MySQL, or file caches which has helped speed up other types of
transfers as well. Even with the relatively short time that mod_fcgid
has
been in place it has been faster, more reliable and more sane than
mod_fastcgi
. Whichever one you pick, make sure to benchmark your server and
check your error logs to solve common issues, the issue may not be what FastCGI
module you picked but rather PHP itself that is causing the errors!