mpm-worker versus mpm-prefork, and mod_php versus fastcgi

*Caution: nothing but geek-content here*

So Apache 2.2 has a couple of “stable” mpm’s, namely prefork and worker.

Prefork is the old tried-and-true method, where the server spawns $StartServers httpd processes, and on-demand starts additional up to $MaxClients. Each subprocess handles $MaxRequestsPerChild requests, then dies and is replaced as needed.

Worker, on the other hand, starts $StartServers httpd processes, and on each process runs up to $ThreadsPerChild. Each thread serves requests (the same as processes on prefork), and when any given process’s child threads hit $MaxRequestsPerChild, the process kills its idle threads, unpools its working threads and waits for them to finish, then dies.

Sounds cool, right? Threads are lighter than processes, so having 5 processes running 20 threads each sounds better than having 100 processes. I got caught up in that and decided to try it on a large-ish site (namely gotwoot, and the 20-odd other sites hosted on that box).

Well, it turns out Worker isn’t as stable as I was hoping. At least for me… one of the sites we host is a huge sender of fairly large files and file streams. When apache processes under mpm-worker try to die, they wait until all the threads are done sending… but if the children are sending for hours, it’s going to take hours for these otherwise-defunct processes to die. If we were talking about just one process taking that long to die, it wouldn’t be a big deal because it wouldn’t interact with anything else. But somehow in that interaction mode, various modules start behaving badly.

So I was running mod_php (only using threadsafe modules) on mpm-worker, and every couple of days I’d see random problems. Sometimes it was zero-byte replies from php, other times it was php segfaulting, still other times it was apache itself dropping empty page replies.

I got sick of that, so I switched over to mpm-prefork and php on fastcgi. Things seem to be better now… it gives me user-mode php, and because of that APC maintains a per-site cache. It’s running fcgi processes on demand, which is also cool ’cause if a site doesn’t get traffic, it doesn’t keep a running php process.

Overall, my system load is a bit lower and things just “feel” more stable with prefork+fcgi. In the next couple days I should actually _see_ whether it’s more stable or not… but either way, I guess there’s value in feelings too :p.

4 Responses to “mpm-worker versus mpm-prefork, and mod_php versus fastcgi”

  1. Savaal Says:

    I was wondering if I could get some more information on the prefork+fastcgi build you are running. I am currently using a windows system for my dev environment, with apache and php using the winnt mpm. This sucks for concurrency, since php is not designed for threaded use, and if one user is in the throes of a long file i/o, other users have to wait until that user is finished before they can have their request taken, likely due to the way the windows mpm works. See, I need separate instances of php to run concurrently. With my current config, apache spawns one instance of php that is shared with all apache requests. I was hoping that if there were multiple processes of apache, that there would be multiple processes of php, as well. Thoughts? Oh, and for bonus points, what is the currently preferred distro of linux for webserver with php? Thanks in advance.

    Savaal

  2. complich8 Says:

    I’ll start off … I don’t know much about mpm_winnt, other than that it’s supposed to spawn worker threads like a simpler mpm_worker. What I _do_ know is that mpm_prefork is pretty well windows-only :p.

    I don’t know exactly how you’re set up on that system, but it sounds like you’ve got php running as a cgi instead of fcgi? Because fastcgi should be able to handle simultaneous requests … if one fcgi process is too busy to handle other requests it should spawn another. At least, that’s how it works in linux. Incidentally, if you were using mod_php, every thread would have access to its own php instance-ish sort of thing.

    As for PHP’s thread safety, that only really comes into play if you’re using non-threadsafe third party php modules. Most people aren’t, so for most people it’s a non-issue…

    Preferred linux distros… debian family (including ubuntu), redhat family (including rhel, centos and fedora) and freebsd are the most common… but it’s all a matter of preference there, they’re all legitimate good choices…

  3. Jase Says:

    How about MPM worker with fastcgi to recommend that compared to MPM Prefork? I have an upload script but that uses mod_perl.

  4. complich8 Says:

    I haven’t tried it. Honestly, prefork works pretty well if though, so worker isn’t really getting you a whole lot other than a shorter process list. At least for me, didn’t make sense.