Nginx – How to keep Apache from falling over

apache-2.2magentonginxperformancePHP

I have a pair of servers hosting a single Magento ecommerce site with moderate traffic (60k page views per day reported from google analytics, I think about 80k reported on the server itself). The database server runs smoothly and quickly, aside from a rare occasional hiccough, but the apache server has been falling over every so often.

I have set up magento to use the recommended PHP caching (APC), as well as holding its own cache files in a 1.5 gig tmpfs (this tmpfs regularly gets pretty full, and I have a script running to clear cache files when the tmpfs is more than 80% full). I serve most imagery from amazon cloudfront. I recently set up nginx as a reverse proxy to apache (nginx also serves the static files). I have configured apache to the best of my ability – keepalives and hostnamelookups are off, and the prefork is configured as follows:

<IfModule prefork.c>
    StartServers      50
    MinSpareServers   50
    MaxSpareServers  100
    ServerLimit  512
    MaxClients   256
    MaxRequestsPerChild 400
</IfModule>

I've not turned off .htaccess files, and access logging is on. I know there are some modules I can turn off. I'm not sure what effect any of those three changes would have, if any.

The apache server is a VPS with 6 gig of RAM. As of the time of writing the server is reporting load average: 17.77, 18.27, 49.76, but there's about 2 gig of RAM free. When it goes really bad, the load goes to 120+ and stays there – restarting apache brings the site back up and the load back down.

vmstat is (while the server is reporting the load above), I think, showing a CPU idle value fluctuating between 0 and 70 or so. iostat is showing an iowait value between 0 and 0.2%.

I'm a bit stuck. What little I know is telling me that the problem is that the CPU is overloaded as a result of combination of the code being run, and the number of users. But I'm not experienced enough to be certain that that is the problem. If that is the problem, I think the solutions are to either improve the code or to split the site hosting over two VPSes with a load balancer.

So, I guess my questions are:

  1. What else can I do to find problems or bottlenecks on the server?
  2. Are there any obvious changes I can make to the server config to improve this?
  3. Is it a good idea to set an automated system to restart apache when the load goes above a certain level?
  4. From the above, how likely is it that the site has outgrown the server?

Edit:

I found something weird – /var/spool/mail/root was large … 38 gig. That sounds … unhealthy. Could that be the problem?

Best Answer

Magento and Zend Framework are quite CPU-heavy, as you noticed. The best way to avoid the CPU load is simply but rendering any content only once, until it changes. Most parts of your catalog don't change that often, and often only the shopping cart block on your page, or the 'most popular items' block are the only dynamic parts.

I would suggest putting a Varnish cache in front of Apache. This gives you high-performance page-caching that can seriously offload your LAMP stack. We recently survived a very public launch of a website thanks to Varnish and I was seriously impressed by the speed and low cpu-load. Varnish is free, and flexible enough to cache entire pages, or cache only the relatively static parts and include the cart dynamically.

However, Varnish will not cache much on a default Magento installation, since there's a lot of per-user dynamic content, cookies, etc. A Magento module such as 'PageCache powered by Varnish' modifies Magento to work well with Varnish. It also provides a Varnish configuration file that matches the Magento setup. These two together make for a very efficient setup. It's a commercial module, but much more affordable than a more powerful server would be.

The parts your offloading to a CDN or Nginx are not your real problem, although it does help. Even Apache can handle quite a number of static requests. You need to cache the stuff that takes effort to generate again and again, i.e. your dynamic parts.