Wed, 05 May 2010 (1759 EST)
So, I had an issue with my poor overworked web servers. Average traffic would use at least 6 gigs of RAM, with each Apache prefork child using an average of 16 megs of ram. So during heavy traffic days, one or more of the web servers would actually start to swap unless I put a less then desirable cap on max connections. I'd heard for years that Apache Worker was the new hotness, but PHP wasn't considered stable enough to rely on in a threaded environment. There's been sporadic reports of success with "only using a limited set of known stable modules", but not a whole lot of actual Howtos beyond using Fastcgi.

Regarding Fastcgi, I did get it to work to some extend, but had a few issues with race conditions around how fcgi and apache itself reaps and respawns child threads, along with having to restructure a signficant amount of our code to be compatible with fcgi's method of doing things. One such example is we were no longer able to use php ini overrides in htaccess files (because fcgi doesn't get called for htaccess). In the end, it's workable, but a giant pain in the ass, and one more piece of duct tape to have to troubleshoot. It's always nice to have another option in reserve though.

Regarding resource usage, the jury's still out on how much less processor. Although I do know that non php stuff is MUCH faster under worker. But for RAM, which was the main incentive for making this change (more RAM, or more web servers), under load that would previously consume about 6 gigs, I'm currently at 1.6 gigs of usage. Yay!

Anyway, here's a quick rundown on what I had to do to get mod_php working with Apache's Worker MPM. I may write this up in a prettier fashion later, probably after I do it a couple more times.


1.) Grab PHP sources
- mkdir ~/build/;cd ~/build
- wget http://us.php.net/get/php-5.2.13.tar.bz2/from/this/mirror
- tar xjvf php-5.2.13.tar.bz2


2.) Grab Suhosin patch (prevents some nasty buffer overruns etc)
- wget http://download.suhosin.org/suhosin-patch-5.2.13-0.9.7.patch.gz
- cd php-5.2.13/
- patch -p 1 -i ../suhosin-patch-5.2.13-0.9.7.patch


3.) Compile PHP (modify options as appropriate, make sure --enable-maintainer-zts is in your configure for worker)
-- Note that you may need to install various otehr utilities and libraries for the compile to work properly, depending on extensions used.
-- One thing that may help get build dependencies on Debian is 'apt-get build-dep php5', which should download all the packages needed to build the debian php source package.


- ./configure --prefix=/usr/local --with-apxs2=/usr/bin/apxs2 --disable-cgi --with-layout=GNU --with-config-file-path=/etc/php5/apache2 --with-config-file-scan-dir=/etc/php5/apache2/conf.d --disable-ipv6 --with-openssl --without-kerberos --with-pcre-regex=/usr --with-zlib --with-zlib-dir=/usr --enable-bcmath --with-bz2 --enable-calendar --enable-ctype --with-curl=shared,/usr --without-qdbm --without-gdbm --with-db4 --with-libxml-dir=/usr --enable-exif --disable-ftp --with-gd=shared,/usr --enable-gd-native-ttf --with-gmp=shared,/usr --with-jpeg-dir=shared,/usr --with-xpm-dir=shared,/usr/X11R6 --with-png-dir=shared,/usr --with-freetype-dir=shared,/usr --with-gettext --with-mhash=shared,/usr --with-ldap=shared,/usr --with-ldap-sasl=/usr --with-mcrypt=shared,/usr --enable-mbstring --without-msql --without-mssql --with-mysql=shared,/usr --disable-pdo --with-pspell=shared,/usr --without-mm --disable-shmop --enable-soap --enable-sockets --with-sqlite=shared,/usr --with-regex=php --disable-sysvshm --disable-wddx --with-xmlrpc=shared --with-iconv --with-xsl=shared,/usr --enable-zip --with-pear=/usr/share/php --with-tsrm-pthreads --enable-maintainer-zts


- make
- make test
- apt-get install checkinstall (checkinstall will monitor a 'make install' type of command and generate a .deb from it, which will let you satisfy dependencies)
- checkinstall -D make install (It will give you a chance to edit the control variables, I suggest setting "provides" to 'php5, phpapi-20060613, php5-common', and the "version" to something like 5.2.13.threaded for packages that require a specific version of php)


-- I had some issues with packages depending on php5-common, but not recognizing the above "provides" line. To fix that do the following:
- apt-get install equivs
- equivs-control php5-common
- Edit the generated php5-common file in your current directory, specifically to set the needed version and provides lines.
- equivs-build php5-common
- dpkg -i php5-common_*.deb


4.) Make sure debian links your php binaries in the normal places (assumes no other php alternatives are there, and there may be a better way to "group" these with update-alternatives):

- update-alternatives --install "/usr/bin/php" "php" "/usr/local/bin/php" 1
- update-alternatives --install "/usr/bin/php5" "php5" "/usr/local/bin/php" 1
- update-alternatives --install "/usr/bin/pear" "pear" "/usr/local/bin/pear" 1
- update-alternatives --install "/usr/bin/pecl" "pecl" "/usr/local/bin/pecl" 1


4.) Grab and compile non standard php modules (specifically memcache and apc)
- pecl install memcache
- pecl install apc


5.) Install apache worker
- apt-get install apache2-mpm-worker
- If it yells at you about missing dependencies that are LIES because you compiled php and it isn't recognizing your stuff, then you can probably trick it with 'apt-get --ignore-missing install apache2-mpm-worker'


6.) Check that php is working
- Run the php command line by just typing "php". It should hang waiting for input, if things are wrong, it will die with a segmentation fault
- Make sure all your php modules are loaded with 'php -m'
- If you are segfaulting, you can usually track down the issue with 'strace php', which will show you all the system calls (like OPEN(somephpmodule.so, ...)) that php tried to run. The last one will usually be the module that crashed php, and you can try unloading it. You will probably need to be able to compile ALL php modules you need for them to be able to talk to threaded php (zts).
All content/ramblings/etc here are copyright (c) 2004 Erik Jacobson (except for the stuff that isn't). Not to be read before swimming, or taken with alchohol. Anything bad is your fault, anything good is mine.