Thursday, January 31, 2013

Notes on FastCGI and webservers

This post is a distillation of what I've learned over the past couple of months.  There's both new information here, and links to everything else on the FastCGI topic that I've written so far.


  1. mod_fcgid
  2. php-fpm (nginx)
  3. other things I tried to use
  4. concluding remarks


Spawns a child of the Apache master to act as FastCGI process manager.  This PM manages a set of "classes", delineated either by URL after rewriting, or by FcgidWrapper.  The former is how I'm handling the conversion of a CGI site to FastCGI at work.  The latter is what happens when you follow the common configuration advice on the Internet for PHP with mod_fcgid.  (But be careful with that advice.)

I suspect, but haven't tested, that any mod_fcgid wrapper script that does no more than set environment variables and call a binary can be replaced with FcgidInitialEnv directives and changing FcgidWrapper to be the called binary.

The mod_fcgid PM spawns new instances into a class when a request arrives and the class is already full of busy children.  Unlike php-fpm, it does not pre-fork; FcgidMinProcessesPerClass specifies only the number of children to be kept alive after requests are processed.  (Excess numbers of such processes can idle for up to FcgidIdleScanInterval + FcgidIdleTimout seconds, before being killed to meet the min process requirement.)

mod_fcgid doesn't quite handle graceful restart perfectly, due to limitations of Apache.

⇑ Contents

php-fpm with nginx

php-fpm is a separate build of the binary from php-cgi; it's installed into an sbin directory by default and is designed to run as a system service.  It introduces one extra configuration file for the process manager itself, which defines all of the stuff that makes php-fpm awesome.

For those who have used the classic Apache prefork MPM, the options for controlling how many start/spare/min/max servers there are will be utterly familiar.  This is also the configuration file dealing with what user and group to run php-fpm as, whether to chroot it, and so forth.

I have heard that php-fpm can also share things amongst its children, notably apc's storage.  This makes sense, since mod_fcgid starts children independently of each other (there is never a point where the php-cgi processes are owned by a common php parent) and php-fpm is all one unit, but I haven't actually tested it.

⇑ Contents

Other Things I Tried to Use

spawn-fcgi refused to either work or tell me what was wrong.  I got it to the point where I could get it to listen and handle requests from the command line, but not when it was configured identically to run as a service.  Apparently, because the FastCGI spec says not to send non-request-related output or errors to the web server, spawn-fcgi throws them into the bit bucket with prejudice.

I have not, at this point, been able to figure out what the recommended setup of a Perl FastCGI anything (either my work's site or Dancer) actually is under nginx.  Even getting it to work with mod_fcgid was sufficiently arcane that I wrote about it here.  With php-fpm, PHP has coded circles around the Perl community.

I was curious about how Apache's mod_fastcgi would handle php-fpm in the FastcgiExternalServer case, which happens to have no equivalent under mod_fcgid.  However, the current version as of December 2012 didn't compile out of the box with Apache 2.4, and I didn't try any harder to work with it.

⇑ Contents

Concluding Remarks

Given the choice, I would avoid Apache where possible.  mod_fcgid is less problematic than something like mod_perl or mod_php in terms of memory consumption, but it makes for an inflexible process manager and the latency at server reload isn't the best.  And with FastCGI, you must reload it if you want to pick up newly deployed code, since the point is to persist stuff between requests, such as your old code.

On the other hand, if you can get your code up and running on nginx, it is much closer to being ready to run on anything.  Although mod_fcgid is a different animal, if you have a framework, it should work everywhere with less difficulty.

⇑ Contents

No comments: