How to tune Apache web server for performance
What is Apache Server?
Apache or (httpd) is the most widely used web server software available today. It’s developed and maintained by the Apache Software Foundation. Apache is free and open-source and is included by default in nearly all web hosting control panels.
As it Apache that serves your web pages to your visitors, the Apache configuration has a major effect on your server’s performance, and, by extension your website’s performance.
There are several 3rd party tools that can check your Apache configuration and make informed decisions on how best to tune the configuration.
Apache mod_status is an Apache module that allows you to see web server load and connections via an HTML interface that can be accessed in a web browser.
- Total number of incoming requests
- Total number of bytes and counts server
- The CPU usage of Webserver
- Server Load
- Server Uptime
- Total Traffic
- Total number of idle workers
- PIDs with the respective clients and many more.
How to Enable mod_status in Apache
By default, Apache comes with mod_status enabled. You can also enable it in the Apache configuration file as per this article: How to enable the Apache mod_status Page
The Apache2Buddy script is very similar to the MySQLTuner you may have seen. It reviews the Apache configuration and makes suggestions to help with performance and stability.
The apache2buddy.pl Perl script will check the following:
- PHP memory limits
- Memory usage
- Max potential memory usage
- Percentage of total RAM allocated to Apache
- And more!
You can run the script as per this article: How to run Apache2Buddy
ApacheBench Tool (ab)
As part of the standard Apache source distribution, the ApacheBench tool is included for evaluating the performance of HTTP web servers. It specifically shows you how many requests per second your Apache can handle by generating a flood of requests to a given URL and returning the results.
For example, the following command will execute 1000 HTTP GET requests, processing up to 10 requests concurrently, to the specified URL:
ab -k -n 1000 -c 10 "http://example.com/"
- -n [value]: The number of requests to send
- -t [value]: A duration in seconds for which each connection is alive
- -c [value]: The number of concurrent requests to make
- -l: ignore length checking
- -v 2: Output response body & header to stdout
- -k: HTTP Keep-Alive
TIP: if using both the -t & -n flags then -t always goes first
Apache version 2.4 offers three Multi-Processing Modules (MPM) for managing connections.
Back up your Apache configuration file!
Before making changes to your Apache configuration, be sure to back up the configuration file:
- CentOS / RHEL / Fedora: /etc/httpd/conf/httpd.conf
- Ubuntu / Debian: /etc/apache2/httpd.conf
- DirectAdmin: /etc/httpd/conf/extra/httpd-mpm.conf
- cPanel: /etc/apache2/conf.d/httpd.conf
- Plesk: /etc/httpd/conf/
At launch, the prefork module creates multiple child processes, each of which handles a single thread; this can slow down request speeds if there are too many concurrent requests. If this happens, some requests are delayed. To counter this, you can increase the number of child processes that are spawned, however, this, in turn, increases the amount of RAM that is used. Prefork is the safest module and should be used when using non-thread-safe libraries.
Each worker process spawns many threads, each ready to handle new requests. This allows for a greater number of concurrent requests to come in, and thus, lowers the server’s RAM usage. The worker module offers higher performance, but is less secure than the prefork module, and cannot be used with modules that are not thread-safe.
Unlike the worker-based MPM, the event module is only available on Apache 2.4. With a thread dedicated to KeepAlive connections, the event module passes the connection to child processes as soon as the request is made. The event MPM functions with SSL-based connections similarly to the worker MPM, and the ability to handle multiple simultaneous connections. It is especially useful when more than one connection is active at the same time but no one always makes a request at once.
To configure your MPM, you must change a few settings in the configuration. These settings are located in the /etc/apache2/apache2.conf file on Debian/Ubuntu, and the /etc/httpd/conf/httpd.conf file on CentOS/Fedora.
Below, is an example configuration for the MPM prefork module:
<IfModule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestWorkers 150 MaxConnectionsPerChild 10000 </IfModule>
To change the worker, simply replace <IfModule mpm_prefork_module> with <IfModule mpm_worker_module> or <IfModule mpm_event_module> depending on your choice.
You must restart Apache to apply the changes.
systemctl restart apache2
systemctl restart httpd.service
The sections below provide an overview of each MPM module setting.
The StartServers directive sets the number of child server processes created on startup. As the number of processes is dynamically controlled depending on the load, there is usually little reason to adjust this parameter.
The default value differs from MPM to MPM. worker and event default to StartServers 3; prefork defaults to 5; mpmt_os2 defaults to 2.
The MinSpareServers directive sets the desired minimum number of idle child server processes. An idle process is one which is not handling a request. If there are fewer than MinSpareServers idle, then the parent process creates new children: It will spawn one, wait a second, then spawn two, wait a second, then spawn four, and it will continue exponentially until it is spawning 32 children per second. It will stop whenever it satisfies the MinSpareServers setting.
Tuning of this parameter should only be necessary on very busy sites. Setting this parameter to a large number is almost always a bad idea.
The MaxSpareServers directive sets the desired maximum number of idle child server processes. An idle process is one which is not handling a request. If there are more than MaxSpareServers idle, then the parent process will kill off the excess processes.
Tuning of this parameter should only be necessary on very busy sites. Setting this parameter to a large number is almost always a bad idea. If you are trying to set the value equal to or lower than MinSpareServers, Apache HTTP Server will automatically adjust it to MinSpareServers + 1.
The MaxRequestWorkers directive sets the limit on the number of simultaneous requests that will be served. Any connection attempts over the MaxRequestWorkers limit will normally be queued, up to a number based on the ListenBacklog directive. Once a child process is freed at the end of a different request, the connection will then be serviced.
For non-threaded servers (i.e., prefork), MaxRequestWorkers translates into the maximum number of child processes that will be launched to serve requests. The default value is 256; to increase it, you must also raise ServerLimit.
For threaded and hybrid servers (e.g. event or worker), MaxRequestWorkers restricts the total number of threads that will be available to serve clients. For hybrid MPMs, the default value is 16 (ServerLimit) multiplied by the value of 25 (ThreadsPerChild). Therefore, to increase MaxRequestWorkers to a value that requires more than 16 processes, you must also raise ServerLimit.
MaxRequestWorkers was called MaxClients before version 2.3.13. The old name is still supported.
Using Apache2Buddy, or the commands listed below can help determine these values. You can also divide the amount of RAM each Apache process uses by the amount of RAM available (leaving some head room) for other processes.
This command displays the Resident Set Size (RSS) value, which indicates the amount of RAM that each Apache process is using, in kilobytes. Replace httpd with apache2 on Debian or Ubuntu systems:
ps -ylC httpd --sort:rss
TIP: Divide the RSS output by 1024 to give megabytes.
The MaxConnectionsPerChild directive sets the limit on the number of connections that an individual child server process will handle. After MaxConnectionsPerChild connections, the child process will die. If MaxConnectionsPerChild is 0, then the process will never expire.
Setting MaxConnectionsPerChild to a non-zero value limits the amount of memory that a process can consume by (accidental) memory leakage.
For the prefork MPM, this directive sets the maximum configured value for MaxRequestWorkers for the lifetime of the Apache httpd process. For the worker and event MPMs, this directive in combination with ThreadLimit sets the maximum configured value for MaxRequestWorkers for the lifetime of the Apache httpd process. For the event MPM, this directive also defines how many old server processes may keep running and finish processing open connections. Any attempts to change this directive during a restart will be ignored, but MaxRequestWorkers can be modified during a restart.
Special care must be taken when using this directive. If ServerLimit is set to a value much higher than necessary, extra, unused shared memory will be allocated. If both ServerLimit and MaxRequestWorkers are set to values higher than the system can handle, Apache httpd may not start or the system may become unstable.
With the prefork MPM, use this directive only if you need to set MaxRequestWorkers higher than 256 (default). Do not set the value of this directive any higher than what you might want to set MaxRequestWorkers to.
With worker, use this directive only if your MaxRequestWorkers and ThreadsPerChild settings require more than 16 server processes (default). Do not set the value of this directive any higher than the number of server processes required by what you may want for MaxRequestWorkers and ThreadsPerChild.
With event, increase this directive if the process number defined by your MaxRequestWorkers and ThreadsPerChild settings, plus the number of gracefully shutting down processes, is more than 16 server processes (default).
Note: There is a hard limit of ServerLimit 20000 compiled into the server (for the prefork MPM 200000). This is intended to avoid nasty effects caused by typos. To increase it even further past this limit, you will need to modify the value of MAX_SERVER_LIMIT in the mpm source file and rebuild the server.
The Keep-Alive extension allows persistent connections to provide long-lived HTTP sessions which allow multiple requests to be sent over the same TCP connection. In some cases, this has been shown to result in an almost 50% speedup in latency times for HTML documents with many images. To enable Keep-Alive connections, set KeepAlive On.