Recently I launched a project that displayed items in a blog-like format with an attached thumbnail. When I had originally developed this project, I built my thumbnail generator with the intent of adding caching support to it in order to reduce the strain placed on the server during peak usage. Unfortunately, I had forgotten to add the caching support and the product went live without.
When this product was launched, the initial traffic spurt was about 110 users all at the same time. Quickly, I found out that the server’s 5 minute load average had risen from values lower than 1.0 all the way up to nearly 50.0! Panicked, I was able to locate the cause of the load, and traced it down to the thumbnail generator. When I disabled the thumbnails, the load average quickly dropped down below 1.0 again; this promptly confirmed that the thumbnail generator was to blame.
The solution for this issue was actually quite simple and can be applied to nearly any programming language. However, since I was working in PHP, I will present you with a PHP example:
$imageFile = 'foo.png';
$thumbnailFile = 'foo-thumb.png';
if (!file_exists($thumbnailFile)) {
// Generate the thumbnail using GD functions
// The resultant image resource will be $thumbnailImage
// Detail omitted for clarity
imagepng($thumbnailImage, $thumbnailFile);
}
header('Content-type: image/png');
echo file_get_contents($thumbnailFile);
exit();
First off, we determine if a thumbnail image already exists for this file. If it doesn’t, we will use GD to create the thumbnail, with the new image resource being represented by the $thumbnailImage variable. Once the image is generated, it will be written to the file described in $thumbnailFile. However, if the thumbnail file exists, we can skip the thumbnail generation. Then, after all is said and done, we will send the MIME Content-type header, echo out the contents of the $thumbnailFile, then exit the script.
As simple as this solution is, mistakenly forgetting to cache the thumbnails once they’re generated was very detrimental to this product and it kept me busy for nearly an hour contacting to the users who were experiencing issues as a result of it.
An important lesson is taught here, though:
Measure twice, cut once.
Or more appropriately, think things through completely before you actually execute them. This extra measure of planning will save you tremendous amounts of headache. No detail is too small, either!