Nginx and other tweaks to improve Drupal performance
How to quickly identify the cause of site stability and poor performance, alongside some methods that can help tune and improve performance of a Drupal site.
Poor performance of a site for end-users can be a tricky thing to combat, especially on larger sites with plenty of dynamic content. Often the hardest and most stressful part is identifying the source of the problem, as without this it is very difficult if not impossible to make an informed decision on what steps to take to correct the issue.
Example: A Drupal 5 migration to D7
A client of ours who ran a content-heavy Drupal 5 website needed us to migrate their existing site to a fresh, newly-architected Drupal 7 site, along with a responsive redesign. This was an interesting and challenging task, but one that we managed well, launching the site early to great feedback. At the clients request, the new website was to be hosted on their existing hosting package, which to date had worked well for their existing sites.
Fast forward a few months and the website started to experience performance issues due to large bursts of traffic from email campaigns - resulting in periods of downtime where the server was simply unable to deal the volume of requests being made. On more than one occasion this resulted in the server crashing completely causing the site to drop offline. The impact such downtime can have on both the user base and SEO can be extremely damaging, so dealing with such issues swiftly and intelligently is crucial.
The first step when dealing with problems of this nature is to consider exactly which part of the site is slowing down - is it an individual page or set of pages? Is the slowdown related to the front-end or the back-end? i.e. are pages taking a long time to generate, or are assets themselves (CSS, JS, images) contributing to the slowdown. If the problem lies with the speed pages are actually being generated at, it’s a good idea to monitor the CPU load to determine whether the problem is related to poorly constructed or complex PHP scripts, or whether there are an excessive amount of queries running per page. The MySQL slow query log can help examine and determine whether queries are taking a long time to complete.
On a Drupal site it is extremely important to ensure everything is configured correctly for optimal performance on a production site, obvious changes such as caching and compression of pages, CSS and JS are very important, as well as disabling and uninstalling unused or no longer required modules.
With smaller, less traffic intensive sites it is usually enough to enable the Drupal cache and compression and very little else - however with larger sites this can very often not be enough.
In our case, we quickly discovered that one of the primary reasons for poor performance was the volume of complex queries that were running on each page, many from the Views module. Often a number of these content blocks generated using Views contained content that did not change frequently and could be further optimised by setting more aggressive Views caching on a case by case basis. Additional Views and Block caching where possible is extremely helpful where you have a number of Views generated content on one page.
The server resources available to a website play a large part in the overall performance, and often as a site grows in size and traffic increasing, correctly scaling to cope with the additional demand. Often a site will outgrow it’s server and deciding whether to scale upwards using a bigger, more powerful server, or to scale horizontally, i.e. increase the number of servers.
We operate a number of dedicated servers, each running multiple sites, specced and configured to cope with different needs. Moving the site to one of our own boxes - a less crowded server with more resources available allowed us to better tune the MySQL server to cope with the very large database and volume of queries. Tweaking values innodb_buffer_pool_size, query_cache_size, and table_cache amongst others within my.cnf allow MySQL to consume more of the free resources available. The combination of more aggressive per-block and per-view caching combined with more resources available to the MySQL server greatly improved the overall access time of many pages across the site.
The final change we wanted to make to the site hosting setup was to implement a system that would allow the web server to serve static and cached content to anonymous users much quicker - thus improving the overall experience for the end-user while also helping to alleviate some of the pressure on Apache. Our solution here was to introduce nginx as a supplementary web server, acting as a reverse proxy.
Image Source: Parallels
Nginx is a lightweight web server designed to deliver large amounts of static content very quickly - as opposed to Apache which has a higher memory footprint and is less efficient at dealing with large quantities of concurrent connections. Nginx sits in front of Apache and handles requests from site visitors, distinguishing between requests for static content and dynamic content. This information can then be passed to Apache so it can handle requests for dynamic content.
A similar solution would be to use varnish. In this instance setting up Nginx has proven to be a perfect solution and has increased the site performance for anonymous users by an extraordinary amount.
There are various other ways to help further improve performance in Drupal - and as all sites are not created equal, monitoring and tuning each site and environment is an ongoing challenge.