SUSE Conversations


Performance Tuning for Apache on SLES 10

mfaris01

By: mfaris01

April 15, 2008 11:10 am

Reads:317

Comments:1

Rating:0

In a world where more companies are pursuing a more “Green” environment, simply throwing additional hardware resources to improve Apache Web server performance, may not be a viable or popular option. In addition, increasing response times by fine tuning the performance of your Apache Web servers can make a difference on the impression your company leaves on it’s customers, whether your customers are internal or external.

In this article, we will be looking at settings and configurations that will help you get maximum performance out of your Apache Web server with existing hardware resources running on SuSE Linux Enterprise Server 10 (SLES). This Apache Web server can either be a new server or an existing server and it is assumed that there are currently enough hardware resources, namely RAM, so that the server is not frequently swapping to disk. It is also assumed that you have a basic knowledge of SLES 10 and Apache Web server.

The following topics will be addressed:

Apache Server Configurations

HostnameLookups
The HostnameLookups directive enables DNS lookup so that hostnames can be logged instead of the IP address. This adds latency to every request since the DNS lookup has to be completed before the request is finished. HostnameLookups is Off by default in Apache 1.3 and later. Leave it Off and use post-processing program such as logresolve to resolve IP addresses in Apache’s access logfiles. Logresolve is included with Apache.

When using Allow from or Deny from directives, use CAN specify an IP address instead of a domain name or a hostname. Otherwise, a double DNS lookup is performed to make sure that the domain name or the hostname is not being spoofed. The problem with this is, if your Apache Web server is running in a clustered environment or virutalized and the IP addresses can change or be shared between devices. Personally, I’m against hard coding anything, except a DNS A Record, with an IP address, it always comes back to bite you later. You be the judge on this.

AllowOverride
If AllowOverride is not set to ‘None’, then Apache will attempt to open .htaccess file (as specified by AccessFileName directive) in each directory that it visits.

For example:

DocumentRoot /srv/www/htdocs
 <Directory />
 AllowOverride all
 </Directory>
 

If a request is made for URI /index.html, then Apache will attempt to open /.htaccess, /srv/.htaccess, /srv/www/.htaccess, and /srv/www/htdocs/.htaccess. These additional file system lookups add to the latency. If .htaccess is required for a particular directory, then enable it for that directory within the section <Directory> in the configuration file. An example would be enabling it for a specific virtual host or directory, in which, mod_rewrite is used, not for the whole web server.

FollowSymLinks and SymLinksIfOwnerMatch
If FollowSymLinks option is set, then the server will follow symbolic links in this directory. If SymLinksIfOwnerMatch is set, then the server will follow symbolic links only if the target file or directory is owned by the same user as the link.

If SymLinksIfOwnerMatch is set, then Apache will have to issue additional system calls to verify whether the ownership of the link and the target file match. Additional system calls are also needed when FollowSymLinks is NOT set.

For example:

 DocumentRoot /srv/www/htdocs 
 <Directory /> 
 Options SymLinksIfOwnerMatch 
 </Directory> 
 
 

For a request made for URI /index.html, Apache will perform lstat() on /srv, /srv/www, /srv/www/htdocs, and /var/www/htdocs/index.html. These additional system calls will add to the latency. The lstat results are not cached, so they will occur on every request.

For maximum performance, set FollowSymLinks off everywhere and never set SymLinksIfOwnerMatch. Or else, if SymLinksIfOwnerMatch is required for a directory, then set it for that directory alone. Use the directive Options -FollowSymLinks to turn it off.

DirectoryIndex
DirectoryIndex directive explicitly specifies the list of resources to look for, always listing the most likely choice first. If none are specified or found, then a directory listing is displayed.
For example, if a client requests www.server.com/necklace/ and the directive for DirectoryIndex is set, as below, and the file exists, then it is used, otherwise Apache will generate a directory listing of /necklace/.

DirectoryIndex index.html

CGI Scripts
Put all CGI files into a single directory and configure that directory for CGI execution. This prevents Apache from trying to determine whether a request is actually for a CGI component or a static file, which adds latency for processing.

MaxClients
The MaxClients sets the limit on maximum simultaneous requests that can be supported by the server. No more than this much number of child processes are spawned. It shouldn’t be set too low such that new connections are put in queue, which eventually time-out and the server resources are left unused. Setting this too high will cause the server to start swapping and the response time will degrade drastically.

Setting the value for MaxClients can be calculated using this equation:

MaxClients = Total RAM dedicated to the web server / Max child process size

Child process size for serving static file is about 3 MB. For dynamic content such as PHP, it may be closer to 15 MB.

The RSS column in the command

“ps -ylC httpd –sort:rss”

shows non-swapped physical memory usage by Apache processes in Kilobytes.

If there are more concurrent users than MaxClients, the requests will be queued up to a number based on ListenBacklog directive. Increase ServerLimit to set MaxClients above 256.

MinSpareServers, MaxSpareServers, and StartServers
MaxSpareServers and MinSpareServers determine how many child processes to keep while waiting for requests. If the MinSpareServers is too low and a bunch of requests come in, then Apache will have to spawn additional child processes to serve the requests. Creating child processes is relatively expensive. If the server is busy creating child processes, it won’t be able to serve the client requests immediately. MaxSpareServers shouldn’t be set too high, it can cause resource problems since the child processes consume resources.

Tune MinSpareServers and MaxSpareServers such that Apache need not frequently spawn more than 4 child processes per second, (Apache can spawn a maximum of 32 child processes per second). When more than 4 children are spawned per second, a message will be logged in the ErrorLog.

The StartServers directive sets the number of child server processes created on startup. Apache will continue creating child process until the MinSpareServers setting is reached. This does not have much effect on performance if the server isn’t restarted frequently. If there are lot of requests and Apache is restarted frequently, then set this to a relatively high value.

MaxRequestsPerChild
The MaxRequestsPerChild directive sets the limit on the number of requests that an individual child server process will handle. After MaxRequestsPerChild is reached, the child process will die. It’s set to zero by default, that means the child process will never expire. It is appropriate to set this to a value of few thousands. This can help prevent memory leakage since the process dies after serving a certain number of requests. Do not set this too low, since creating new processes does have overhead.

KeepAlive and KeepAliveTimeout
The KeepAlive directive allows multiple requests to be sent over the same TCP connection. This is particularly useful while serving HTML pages with lot of images. If KeepAlive is set to Off, then for each image a separate TCP connection has to be made. Overhead due to establishing TCP connection can be eliminated by turning On KeepAlive.
KeepAliveTimeout determines how long for a process to wait for the next request. Set this to a fairly low wait time, somewhere between two to five seconds. If it is set too high, child processes that are completed, are left waiting for the client, when they could be used for servicing new clients.

Multi-Processing Modules

Apache Web server on SLES 10 provides two Multi-Processing Modules (MPM) to select from, “prefork” and “worker”, which are responsible for binding to the network ports on the server, accepting requests, and dispatching children to handle the requests. Only one MPM can be loaded into the server at any time.

Choosing which MPM depends on various factors such as whether the server is multiprocessor, how much memory is available, scalability versus stability, whether non-thread-safe third-party modules are used, or whether the software running on it is a bit dated.

Let’s take a look at each of the MPMs included with SLES 10.

Prefork MPM uses multiple child processes. Each child process handles on connection at a time and requires more of the system’s resources. It is also more suited for single or double processor systems. Speed is comparable to that of the “worker” MPM and it’s highly tolerant to faulty modules and if a child process should crash, only that child process is affected. Prefork is the default MPM for Apache Web server on SLES 10. In the Novell documentation for SLES 10, general reference to MPM refers to Prefork MPM.

Worker MPM also uses multiple child processes. But it’s multi-threaded within each child and each thread handles a single connection. Worker is fast and highly scalable and the memory footprint is comparatively low. It’s much better suited for multiple processor systems. On the other hand, worker is less tolerant to faulty modules and faulty threads. If a thread crashes, it affects all the threads in a child process. In addition, not all modules are considered “thread safe” and thus cannot be used with worker MPM. Novell also strongly discourages the use of mod_php with worker MPM.

Servers for Static and Dynamic Content

Apache processes serving dynamic content take about 3 MB to 20 MB of RAM. It grows to accommodate the content it’s serving and never decreases until the process dies. For example, an Apache process grows to 20 MB to serve some dynamic content. After completing the request, the memory is freed up to serve any other request. If a request for a 1 KB image comes in, then this 20 MB process is serving static content which could be better served by a 1MB process. The memory is used inefficiently.

You could use two Apache servers, one as the front-end server to serve static contents and one for dynamic contents. Using this method allows for one server the advantage that the static contents are served fast without much memory usage and only the dynamic contents are passed over to the second server.

Request redirection can be achieved by using mod_proxy and mod_rewrite modules. Let’s say you have an Apache server listening to port 80 and another Apache listening on port 8088. Then the following configuration in the first Apache can be used to forward all request, except request for images, to the secondary Apache server.

ProxyPassReverse / http://%{HTTP_HOST}:8088/
 RewriteEngine on                                             
 RewriteCond   %{REQUEST_URI} !.*\.(gif|png|jpg)$
 RewriteRule ^/(.*) http://%{HTTP_HOST}:8088/$1 [P]
 
 

All requests, except for images, are proxied to the secondary server. Response is received by the primary server and then supplied to the client. As far as client is concerned, all the responses appear to come from a single server.

Caching and HTTP Compression

The server uses the gzip or deflate encoding method on the response payload before it is sent to the client. Clients then decompress the payload. Using compression will save bandwidth and improve response time. HTTP Compression can be enabled in Apache using mod_deflate module. The payload is compressed only if the browser requests compression, otherwise uncompressed content is sent. A compression aware browser informs the server that it prefers compressed content through the HTTP request header. Then the server responds with compressed payload

In caching, a copy of the data is stored at the client or in a proxy server so that it need not be retrieved frequently from the server. This will save bandwidth, decrease load on the server and reduce latency. Cache control is done through HTTP headers. In Apache, this can be accomplished through mod_expires and mod_headers modules. There is also server side caching, in which the frequently accessed contents are stored in memory so that it can be retrieved rapidly. The mod_cache module can be used for server side caching. All of these modules are included in SLES 10.

Conclusion

Configuring Apache for maximum performance can be a bit overwhelming. Novell provides optimization for Apache in it’s OES 2 product, but leaves Apache tuning in SLES 10 up to you, which is the way we like it. Understand your web server requirements and experiment with the various available options in a lab environment before you turn the server loose. And always remember to have fun doing it!

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Tags: ,
Categories: SUSE Linux Enterprise Server, Technical Solutions

Disclaimer: As with everything else at SUSE Conversations, this content is definitely not supported by SUSE (so don't even think of calling Support if you try something and it blows up).  It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.

1 Comment

  1. By:AskApache

    This is really great! Thanks for that information.. I had to use this ps command for my OS..

    ps -ylC httpd krss
    

    I use the following command to determine the number of MaxClients on CentOS all 1 line.

    echo $(( 
    $(( `sed -n "s/MemTotal:[\t ]\+\([0-9]\+\) kB/\1/Ip" /proc/meminfo` 
    / 
    `command ps -ylC httpd krss --no-heading|tr -s ' '|cut -d' ' -f8|sort |tail -n1` 
    )) 
    - 20 ))
    

    I have a huge list of Rewrite Examples that are also helpful.

    I would love to see a follow up article on this..

Comment

RSS