====== Apache - Apache Tuning Tips ====== Tips to get your Apache webserver running to it's fullest potential. Many of the tips below are generic and apply to any webserver not just Apache. * Upgrade Apache to the newest version. You may want to try Apache 2.X.X. It has worker threaded MPM and other speed enhancements. Benchmark both with your site and see which one is better for you. * In httpd.conf, set **"HostNameLookups off"** which avoids doing a reverse DNS lookup on every visitor who hits your web site. * In httpd.conf, a good rule of thumb for **"MaxClients"** is divide your total RAM by 5 megabytes. So a server with 1GB of RAM could probably handle a MaxClients setting of 200. You will have to test this. You might be have to set it higher or lower. Setting it to high would be bad because each Apache process consumes some memory. You can only fit a certain number processes in RAM before the web server begins swap things between RAM and the hard drive in a horrid attempt to make things work. The result is a totally unresponsive server with a thrashing hard disk. Suggestions from Willy Tarreau a 2.4 kernel maintainer in this area are the following. "Observe the average per-process memory usage. Play with the MaxClient parameter to adjust the maximum number of simultaneous processes so that the server never swaps. If there are large differences between processes, it means that some requests produce large data sets, which are a real waste when kept in memory. To solve this, you will need to tell Apache to make its processes die sooner, by playing with the **MaxRequestsPerChild** value. The higher the value, the higher the memory usage. The lower the value, the higher the CPU usage. Generally, values between 30 and 300 provide best results. Then set the **MinSpareServers** and **MaxSpareServers** to values close to MaxClient so that the server does not take too much time forking off new processes when the load comes in." * In httpd.conf, busy websites should set **"KeepAliveTimeout"** low. Like to 2 seconds. Keeping it low like this gives the client enough time to request all of the files needed for a page without having to open multiple connections, yet will allow Apache to terminate the connection soon enough to be able to handle many more clients than usual. Some people even suggest turning keep-alives off totally. Willy Tarreau a 2.4 kernel maintainer suggests this. He says "First, disable keep-alive. This is the nastiest thing against performance. It was designed at a time sites were running NCSA httpd forked off inetd at every request. All those forks were killing the servers, and keep-alive was a neat solution against this. Right now, things have changed. The servers do not fork at each connection and the cost of each new connection is minimal. Application servers run a limited number of threads or processes, often because of either memory constraints, file descriptor limits or locking overhead. Having a user monopolize a thread for seconds or even minutes doing nothing is pure waste. The server will not use all of its CPU power, will consume insane amounts of memory and users will wait for a connection to be free. If the keep-alive time is too short to maintain the session between two clicks, it is useless. If it is long enough, then it means that the servers will need roughly one process per simultaneous user, not counting the fact that most browsers commonly establish 4 simultaneous sessions! Simply speaking, a site running keep-alive with an Apache-like server has no chance of ever serving more than a few hundreds users at a time." * Serve web graphics (such as jpg,png,gif files) or static files (html,javascript,CSS) from another machine if possible. Try to use a light weight daemon like thttpd for this. Make sure the thttpd version supports keep alives. Set your keep alives low (like 2-3 secs). Doing this will free up Apache for handling the dynamic PHP/Perl stuff if you have it. * Keep your Apache lean and mean. Compile Apache with as few modules as needed. Before compiling (before your run make), edit the /apache_1.x.x/src/Configuration file put a # in front of any AddModule lines you don't need. * If you don't need traffic logs (such as a site that only serves graphics) then use the **TransferLog** directive in httpd.conf to redirect log entries to /dev/null/ * Unless you insist on using **.htaccess** files to control access to certain directories (there are other ways to do that), in access.conf (or httpd.conf in newer versions of Apache) in the section, set **"AllowOverride None"** so that Apache will not bother looking for an .htaccess file in each directory with each request. * DO NOT serve web pages or write web traffic logs on a networked disk drive (ie. NFS or SAMBA networked disks) -- read and write to local disk drives only. NFS I/O operations incure huge overhead. * DO NOT run Apache (httpd) via the tcpd wrapper in /etc/inetd.conf. Apache can be started when the machine boots by either adding the startup command to your rc.local file or by placing the httpd startup script to your /etc/rc.d/rc3.d/ directory. If you want some mechanism to block requests by IP address then use the "deny from" directive in the Apache's conf files or in a .htacess file. * Avoid using SSI tags if you can. * In CGI scripts: * File I/O: Open as few files as possible. Be sure to explicitly close each opened file. Stop reading the file as soon as you found the data you need. Consider structuring data files into fixed-length fields and using read() function to skip ahead to just the part of the file you need to read. * Shell Commands: Call shell commands via their full path: eg. use '/bin/date' instead of just `date` in a perl script. * If your site is mostly CGI driven, by all means use mod_perl. See http://perl.apache.org/. Mod_perl gives huge Perl speed increases. * Perl programmers should study "Effective Perl Programming" by Joseph N. Hall (an Addison Wesley book) and "The Perl Cookbook" by Tom Christiansen (an O'Reilly book) -- two good texts for optimizing perl code. For example, you can preallocate the memory for a hash that will contain 256 items like so: "keys(%names) = 256;". * Avoid having more than 1000 files in your web page directory. Organize your web page files into subdirectories. The more files there are in a directory, the longer it takes to locate that file during a request. * Put as few graphics in your web pages as possible. Make sure each image is run through an image compressor. * Stress test your web site. Run Apache Benchmark program (called "ab") in Apache's /bin or /sbin directory. The ab program will simulate heavy traffic by running multiple simultaneous requests on any web page you want for as long as you want then measures the load and response times. Very useful for measuring the effects of your tuning efforts. * The single biggest hardware issue affecting webserver performance is RAM. A webserver should never ever have to swap, swapping increases the latency of each request beyond a point that users consider "fast enough". This causes users to hit stop and reload, further increasing the load. You can, and should, control the MaxClients setting so that your server does not spawn so many children it starts swapping. * I should not have to say this but do not run any extra non-needed processes on the server (X windows,mail,samba, or whatever). * Turn on follow **FollowSymLinks** (Options -Indexes FollowSymLinks). This saves a few io reads. Apache doesn't have to check if its a symlink, it just goes ahead and traverses. Turn off **SymLinksIfOwnerMatch** to prevent additional lstat() system calls from being made. * Increase your kernel's tcp/ip write buffers so that most, if not all generated pages can be written without blocking. If the page that Apache generates fits in this buffer, then Apache's write() call returns instantaneously, then Apache hands the socket over to lingerd, logs the hit, and is immediately free for more work. If the page doesn't fit, then write() blocks until the client has acknowledged part of the data, which can take several seconds. To change this, use the **SendBufferSize** directive from httpd.conf. However, this directive cannot increase the buffer size past the kernel limit. Changing this kernel limit is OS-specific. Under Linux you can set it by echo'ing a larger number (eg. 131072) into /proc/sys/net/core/wmem_max, before starting Apache. If you change wmem_default as well as wmem_max, then the SendBufferSize directive is not needed. * Disable **ExtendedStatus** unless you're actually debugging. Same goes for mod_info. * Use a reverse proxy cache in front of your server farm. This will return cached contents without hitting the application servers.