My Linode web configuration hasn’t particularly been optimised much beyond the default settings, so it was a kick up the backside to do something when the email alerts warned me about high load.
Incidentally, the investigation showed a client’s site was being swamped by large number of connections, and strangely enough, most of those connections (if not all) came from a class B subnet which the IP lookup tools point to the MoD in London. Bizarre.
Note: the rest of this post is mostly concerned with removing mod_php+MPM prefork completely on a server with Virtualmin GPL to use FCGId + MPM worker + PHP CGI, so it won’t really apply to you if you do not have mod_php installed nor Virtualmin .
The configuration is in a typical LAMP stack with Debian + Apache + PHP, with Apache 2.2 in the default Debian configuration with MPM prefork, and Virtualmin for ease of client site configuration. PHP has been set up to run via mod_fcgid which allows better process separation between each virtualhost when compared to mod_php.
MPM prefork spawns one child process per request. This module is not the most efficient out there, but it works with everything including mod_php (it is required to run prefork with mod_php). In comparison, MPM worker spawns child processes which in turn spawns multiple threads to handle each request. Threads are like lightweight processes which can share resources and memory space with each other within the same process, so a threaded design can be quite efficient. The downside with threads (and this is a simplified overview) is the trade-off of sharing space – crashed threads can bring the others down within the process, whilst the isolation of process-based design is inherently more secure.
There is one other module – the event MPM which as an experimental variation of the worker MPM, and strives to work like the event-based Nginx (which itself is gaining huge kudos points for its efficiency), but it’s still relatively immature and is only properly supported with Apache 2.4 onwards.
It’s clear that the worker module has good potential for serving more users, however there were a few snags with my Virtualmin-enabled setup.
Enabling mpm_worker means mod_php cannot be enabled, and incidentally, mod_php was somehow installed alongside FCGId. Virtualmin, which installs FCGId by default, handles this by disabling mod_php in each virtual server configuration that has been enabled to use FCGId:
php_admin_value engine Off
However, only mod_php understands this directive, so when mod_php is disabled, Apache will refuse to start, and report that it does not understand “php_admin_flag”!
So, to move away from mod_php + mpm_prefork:
If you are certain that you are not using mod_php, most of this can be skipped.
1. Configure each site in Virtualmin to use FCGId.
This can be performed by going to Server Configuration > Website Options > Website and PHP Options: PHP script execution mode for each virtual server.
2. Remove any php_* directives from the Apache virtualhost configurations.
To preview the PHP directives present:
grep "^php_" /etc/apache2/sites-enabled/*.conf
This gives an output like
/etc/apache2/sites-enabled/thomjetson.com.conf:php_admin_value engine Off /etc/apache2/sites-enabled/test.mysite.com.conf:php_value suhosin.session.encrypt Off /etc/apache2/sites-enabled/unixlandworld.com.conf:php_admin_value engine Off
I simply did a bulk edit to comment them out with a #:
sed -e 's/^php_/#php_/' -i /etc/apache2/sites-enabled/*.conf
3. Move any necessary php directive options to each site’s php.ini
An example is
These should be configured in php.ini either directly (Virtualmin for Debian usually places them in /home/webuser/etc/php.ini) or via the virtual server’s configuration screen in Virtualmin: Services > PHP 5 Configuration > Edit Configuration Manually
[suhosin] suhosin.session.encrypt = 0
4. Disable mod_php
Optional as installing mpm_worker will do this anyway, but provides a quick test with Apache failing to restart if there are still php directives lying around.
From the command line:
or via webmin: Servers > Apache Webserver > Global configuration > Configure Apache modules
5. Install mpm worker
As root, or sudo:
apt-get install apache2-mpm-worker
This will remove mpm-prefork and mod-php5 as conflicting dependencies, and restart Apache2 with mpm-worker. Redhat/CentOS users would change their configuration instead (/etc/sysconfig/httpd).
Piece of cake.