How can a webmaster update their Drupal web site without disrupting service?
If availability is not important, a webmaster may modify the code in-place, taking the site offline for a several hours while update scripts are run and last-minute bugs are fixed. Otherwise, if multiple servers are available, another set of solutions arises.
What follows is an outline for managing concurrent versions of a single web site and for switching the active version. The outline assumes a shared hosting environment with access to a unix-type filesystem.
Perhaps that sentence alone is enough to trigger ideas in the minds of experienced Drupal multisite users. But if you want more details, read on!
Overview
Let's begin by taking a look at the filesystem at the root of the Drupal installation.
- .htaccess
- version1/
- CHANGELOG.txt
- cron.php
- files
- ...
- version2/
- CHANGELOG.txt
- cron.php
- files
- ...
In this arrangement, the directory version1/ handles normal traffic. When the webmaster decides to activate version2/, the switch can be made in a fraction of a second by typing rm default && ln -s version2 default.
Until that time, both of the site versions can be accessed concurrently by knowledgeable staff. Preparations for a site update can occur behind the scenes.
Implementation
Beyond the actions a webmaster normally takes when install Drupal, as of the time of this writing index.php needs two extra lines. An extra .htaccess file is needed, too.
Continuing with the same example, if version1/ is the current version, we don't want "version1" in our hyperlinks because we don't want site visitors to know about the sub-sites. To accomplish this, index.php needs to modify some path-related variables.
...
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$GLOBALS['base_path'] = '/';
$GLOBALS['base_url'] = 'http://example.com';
$return = menu_execute_active_handler();
...
The path modifications occur after the bootstrap process, which interacts with the cache, and before theme functions begin rendering hyperlinks.
To make the current version transparent to the site visitor, we introduce an additional .htaccess file in the root of the Drupal directory. I frequently copy the main Drupal file and strip out the PHP settings. Near the bottom, after Apache checks for existing files and directories, one line is changed to redirect all remaining traffic to the sub-site.
...
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /default/$1 [L,QSA]
...
Performance
The cost of performing internal redirections with Apache is probably the first performance issue that comes to mind. An extra internal redirection will definitely reduce performance, so we waste no time looking for ways to reduce that penalty.
Intuitively, a filesystem link is cheaper than Apache's internal redirection. We can bypass many of the redirections by linking to the items in the default/ directory, which is also a filesystem link to the current version of the site. The directory structure is now more complicated, as shown below.
- cache -> default/cache
- default -> version1/
- favicon.ico
- files -> default/files
- .htaccess
- misc -> d/misc
- robots.txt
- themes -> default/themes
- version1/
- CHANGELOG.txt
- cron.php
- files
- ...
- version2/
- CHANGELOG.txt
- cron.php
- files
- ...
Is this extra complexity worthwhile? Is our intuition correct?
After a little statistical exercise, the results come back inconclusive. (I took 40 sets of 50 samples without the filesystem link to bypass Apache's internal redirection. Then I did the same thing with the link. This was done in a way that did not involve PHP.)
- Without the filesystem link
- Mean of the sample means: 4.250 requests per second (rps)
- Standard deviation of the sample means: 0.670 rps
- With the filesystem link
- Mean of the sample means: 4.168 rps
- Standard deviation of the sample means: 0.805 rps
At the 95% confidence level, the extra filesystem link was somewhere between 0.294 rps faster and 0.459 rps slower than without the link. In other words, the extra filesystem links didn't really matter.
Live demo
This technique was developed and employed for Quality Focus, LLC.
- Main site: http://qcfocus.com
- Current version: http://qcfocus.com/7
- Candidate version: http://qcfocus.com/8
Notice that links from the current revision lead to the main site while lines from the candidate revision stay within that revision.
Conclusion
A two-line hack to index.php, a copied and modified .htaccess, and some extra directories. The tools are relatively simple, and I hope simple enough to be useful.
So, how do you manage major site updates without disrupting service?