Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I run an image hosting website. My server can get anywhere between 8 requests a second to 20 requests a second during peak hours. I am currently running a server on the current hardware:

Processor AMD Hexa-Core Speed 6 Cores x 2.8 GHz (3.3 Turbo Core) RAM 16 GB DDR3 ECC Hard-disk space 1,000 GB (2 x 1,000 SATA) RAID Software RAID 1

Full specifications http://www.1and1.com/ServerPremiumXL?__lf=Static&linkOrigin=ServerPremium&linkId=ct.btn.package.xl I ordered the XL6 server.

I don't statically serve the images since they are stored elsewhere on the server. They are dynamically loaded on each call with readfile(). The server has been taking a beating recently and I want to know how I can optimize the server to be able to handle this kind of traffic with ease.

I have installed eaccelerator which seems to be helping, but not helping enough. I also had X-SendFile installed at one point, which seemed to help also, but I had to remove it temporarily because of issues with Apache, although I want to try to get it back on.

I am basically here asking for advice so I can vamp up my server to easily handle 50 req a second (unless this is just completely unreasonable). I myself am a developer and do not know too much about linux/apache, although i know the basics. I am also willing to learn. Thanks for any information.

share|improve this question

migrated from stackoverflow.com May 2 '12 at 13:40

This question came from our site for professional and enthusiast programmers.

    
50 per second sounds downright tame unless you're generating gigantic images on the fly... Why not static files? Can you perhaps locally cache the most frequently used images? –  sarnold May 2 '12 at 6:14
    
I'm fairly sure that eaccelerator is cache'ing the files already for me? Or is it not? –  MasterGberry May 2 '12 at 6:22
    
I agree with @sarnold, your system should easily be able to manage this kind of traffic. You should try to evaluate load times in your script execution, I made a small [snippet for evaluating specific load time on function level](gist.github.com/2214421 ) some time ago, maybe it could be of use. –  nyson May 2 '12 at 6:25
    
first you have to find out wheres the bottleneck, use the /server-status (if you have this module enable, otherwise enable it) and/or use apachetop. we cant really help u when we dont know wheres the problem etc. –  K1773R May 2 '12 at 6:28
1  
@kristovaher: in one terminal, I typed date but didn't yet hit enter; then I typed my web page URL into my browser, but didn't yet hit enter; then I swapped between the terminal and browser, hit enter twice quickly, and then scrolled the browser window down as images progressively loaded. At the end, I hit up-arrow enter in the terminal again. Seven seconds difference. I knew it wasn't going to be instant, and with 542 images, half a second here or there isn't going to change the fact that it is well above 50 per second. :) I wouldn't do this daily; date; wget --mirror; date might do... –  sarnold May 2 '12 at 6:35

3 Answers 3

up vote 5 down vote accepted

There are a number of things you can do here. For one, you mention that you serve the images with readfile()? This can be a culprit here since it is PHP that is serving the images. That is not inherently much slower than serving them static and does come with multiple benefits (like dynamic image processing), but you can have a number of pitfalls as a result. From server standpoint it is always much faster to serve images as static.

First of all, is your script - the one that returns images - pushing out correct headers? That is, are you sending out Cache-control and Expires headers that tell user agents to cache images? Your traffic might come from the fact that your images are served either all the time or too frequently. Also send a Last-modified header.

You can also send a Not-modified header as a response if a user agent makes a request for a file and you know it has not been modified since the date that user agent provides.

If you already do set all proper headers and make sure that user-agents are not uselessly requesting the data that they already have, then your problem is in your web server. Have you done any performance testing to see if this affects only images or if it affects all requests in general?

I suggest trying to see how powerful your server is when serving regular (PHP) requests. See how long your pages themselves take time and compare it against requests for an image. I suggest a good tool such as Pylot for this (it is command-line, but really useful).

(Note that for comparison it is useful to compare a page with X size to an image of X size so that bandwidth is equal and you can just grade performance).

EDIT:

Cache headers that tell user agents that make the request to cache the file for as long as possible are as follows:

$lastModified=filemtime($myPicture); // File location of your image
$cacheDuration=31536000; // One year
// This tells user agent to keep the cache for one year
header('Cache-Control: public,max-age='.$cacheDuration);
header('Expires: '.gmdate('D, d M Y H:i:s',(time()+$cacheDuration)).' GMT');
// This tells the user agent the last modified time of your image
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$lastModified).' GMT');

Serving Not-modified headers is a bit more complicated:

// Testing if the servers known last modified time is different from the last modified time of file on your server
// If those times are the same, then we will not return the image and just tell the user agent to use their cache
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>=$lastModified){
    // Cache headers (Last modified is never sent with 304 header, since it is often ignored)
    header('Cache-Control: public,max-age='.$cacheDuration);
    header('Expires: '.gmdate('D, d M Y H:i:s',(time()+$cacheDuration)).' GMT');
    // Returning 304 header
    header('HTTP/1.1 304 Not Modified');
    die();
}
share|improve this answer
    
The issue with using static files is I use a shorter URL to serve the images. The actual images are stored in a different part of the server outside of the public_html directory, and organized by year, month, and day. So it's not possible for me to just serve them statically. The X-sendfile mod i had for apache was probably the closest thing. So you recommend using Last-Modified: header in my headers, and no I am currently not using any cache-control or expire headers, as I am not 100% sure how i should be configuring them. Do you suggest using all of these? Got any good guides? –  MasterGberry May 2 '12 at 6:41
    
I did some benchmarks and my framework (WWW Framework, which also serves images dynamically) is no more than 10-15% slower when serving images (even dynamically edited ones, like applying grayscale) compared to static images without PHP. My image handler for it is here: code.google.com/p/www-framework/source/browse/engine/… . As for these headers, I will update my answer in a minute with examples. –  kristovaher May 2 '12 at 6:53
    
My image handler is very similar except I am using readfile() instead of imagejpeg() and imagepng() and imagegif(). Is one faster than the other? I also have a few database queries run to update the number of hits each image has received in the database. Oh, something I forgot that I just thought of. I serve images under the following url: http://i.website.com/asdasd.jpg which then I have .htaccess redirect to http://www.website.com/images/asdasd.jpg to help shorten the URL some more for the users to use. Could this be effecting my speed of the server? Will post code in a sec. –  MasterGberry May 2 '12 at 7:00
    
RewriteCond %{HTTP_HOST} ^i.website.com RewriteRule (.*) http://www.website.com/images%{REQUEST_URI} [R=301,NC,L,NS] –  MasterGberry May 2 '12 at 7:01
    
I added examples about how to serve images with proper headers with PHP. –  kristovaher May 2 '12 at 7:04

my question is, do you really want to route them through PHP on output? that's an awful lot of multiplied processing considering each page probably views multiple images. so PHP becomes the bottleneck, and it's a scripting language.

possibly pre-process the thumbnails to specific site-required sizes beforehand, and store those copies. takes up extra space, but you will get somewhat more speed I would think if the images can link directly to a file rather than being served up through PHP.

share|improve this answer
    
Have to do it via PHP due to the file structure and how i am shortening the URL of the images. I plan to rebuild my website in python eventually which will be faster, but for now I need to figure out what's going on server side first... –  MasterGberry May 2 '12 at 6:44

This might be just as much a question as it is an answer, so maybe someone with experience can weigh in on this. Would a RAM disk be of any benefit in this situation? I don't know how many images you host, but what if you were to place the most commonly accessed images (with the obvious limit of how many will fit in the ram disk) into the ram disk. Then whenever you or a user adds or edits a photo, you make the change to a permanent copy on the disk as well as to the copy stored in RAM. With that many requests coming in, you'd think that cutting out the "read from disk" step would help speed things up.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.