smddzcy | yet another dev

Migrating from Apache/mod_php to Apache/php-fpm

☕️ 2 min read

Today is the day. After receiving tons of emails from Jetpack and seeing my server down countless times over the last couple of weeks, I finally made the switch from mod_php to php-fpm.

"Your site is extremely slow."
"Your server is not responding."

These are basically what I received from Jetpack over and over again. It was totally expected though. My server has the cheapest configuration from DigitalOcean (1 CPU, 512 MB memory) and I host all of my applications on this weak little fella. One of those applications is BOUN Course Planner, which was extremely popular for the last couple of weeks because of the online registration period. It attracted 2000 people per day, but my little server couldn’t handle that much traffic. Specifically, it couldn’t handle more than ~30 active connections.

I made a small load test and noticed that the Apache processes consume all the memory when there are multiple active connections. The source of the problem was obvious: Apache PHP module, a.k.a. mod_php. It is the module that allows Apache to interpret PHP files, and it’s known to suffer from this kind of memory problems.

The solution was simple. I removed mod_php, tried to migrate to NGINX with php-fpm, failed (was too lazy to configure the NGINX), migrated to php-fpm only. Here is what I did and what you should do to migrate to php-fpm if you are running Ubuntu 16.04 and using PHP 7.0:

sudo apt-get remove libapache2-mod-php7.0 # remove mod_php
sudo apt-get -y install php7.0-fpm libapache2-mod-fastcgi # install php-fpm
sudo a2dismod mpm_worker mpm_prefork # disable the conflicting modules
sudo a2enmod actions fastcgi alias rewrite mpm_event # enable the required modules

Add the following configuration to /etc/apache2/conf-available/php7.0-fpm.conf:

<IfModule mod_fastcgi.c>
    SetHandler php7-fcgi .php
    Action php7-fcgi /php7-fcgi virtual
    Alias /php7-fcgi /usr/lib/cgi-bin/php7-fcgi
    FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi -socket /var/run/php/php7.0-fpm.sock -pass-header Authorization -idle-timeout 3600
    <Directory /usr/lib/cgi-bin>
        Require all granted

Then enable the configuration and restart the services to see the changes:

sudo a2enconf php7.0-fpm # enable the php-fpm configuration
service apache2 restart
service php7.0-fpm restart

That’s all. You should have your web server up and running with php-fpm now.

I made some other load tests after the migration, and here are the results:

  • Test 1: 10 to 200 active clients over 1 min (Link to the results) Response time: 143 ms on average, 276 ms with 200 active connections. Error rate: %0.00 (No connection drop, no timeout)
  • Test 2: 10 to 500 active clients over 1 min (Link to the results) Response time: 350 ms on average, 610 ms with 500 active connections. Error rate: %0.00 (No connection drop, no timeout)

Memory usage during the tests: 52% - 67%. Outcome: php-fpm is clearly better than mod_php.