How to optimize Apache performance


 

Squeezing the most performance out of your Apache server can make a difference in how your Web site functions and the impression it makes. Even fractions of a second matter, especially on dynamic sites.

 

 

1. Selecting the correct MPM

Apache is modular in that you can add and remove features easily. Multi-Processing Modules (MPMs) provide this modular functionality at the core of Apache -- managing the network connections, binding to ports and dispatching the requests. MPMs let you use threads or even move Apache to a different operating system.

Only one MPM can be active at a time, and it must be compiled in statically with:
--with-mpm=(worker|prefork|event).

 

The traditional model of one process per request is called prefork. A newer, threaded, model is called worker, which uses multiple processes, each with multiple threads to get better performance with lower overhead. Finally, event MPM is a module that keeps separate pools of threads for different tasks.

 

  • To determine which MPM you're currently using, execute httpd -V
  • You can view what Apache modules have been compiled by entering httpd -l

 

Choosing the correct MPM to use depends on many factors. On the surface, threading sounds better than forking, if all the underlying modules are thread safe, including all the libraries used by PHP.

Prefork is the safer choice; you should do careful testing if you choose worker. The performance gains also depend on the libraries that come with your distribution and your hardware.

 

  • Worker MPM
    uses multiple child processes that can have multiple threads each. Each thread handles one connection at a time. Worker generally is a good choice for high-traffic servers running Apache versions prior to 2.4 because it has a smaller memory footprint than the prefork MPM. However, it suffers due to incompatibilities with non-thread safe libraries.
  • Event MPM
    is threaded like the Worker MPM, but is designed to allow more requests to be served simultaneously by passing off some processing work to supporting threads, freeing up the main threads to work on new requests. Event MPM functions identically as worker MPM in the event of SSL connections. Apache has the lowest resource requirements when used under the Event MPM. Event MPM is only available from Apache 2.4
  • Prefork MPM
    uses multiple child processes with one thread each. Each process handles one connection at a time. On many systems, prefork is comparable in speed to worker, but it consumes more memory. Prefork's threadless design has advantages over worker in some situations: Prefork is the safest module and can be used with non-thread-safe third-party modules. Prefork MPM is also easier to debug on platforms with poor thread debugging support.

 

Regardless of which MPM you choose, you must configure it appropriately. In general, configuring or performance tuning an MPM involves telling Apache how to control the active and inactive workers and whether they're threads or processes. From Apache 2.2 Prefork is the default MPM.



Other MPM options

The optional mod_mpm_itk Apache module causes the Apache process to switch to the domain owner's user identifier (UID) and group identifier (GID) before it responds to the request. This allows each user to isolate their files from others with the standard file permission settings. It essentially allows for the isolation of each vhost directly in its configuration file.

The main limitation of the ITK lies in its performance, because it creates and then destroys a process for each query, which degrades performance, especially compared to Prefork or Worker MPM.

mod_mpm_itk does not function as a stand-alone MPM. You must install the prefork MPM in order to use the MPM ITK module, which needs to be installed separately.

mpm_winnt is part of Apache’s integration into the Microsoft Windows operating system. Usage of this MPM is a requirement when utilizing Apache on this system type.

There are other experimental MPMs available, but we do not recommend to use them in a production environment.



2. Locating Apache.conf

To start, locate and open the Apache configuration file and find the MPM directives section:

  • 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/

If you are using nano, vi or vim: once you open the file, you can find the directives by scrolling through the file. Using VI or VIM you can also search by typing forward-slash ‘/’ and typing the exact string that you are looking for (search is case specific).

Below you can find an example configuration for the MPM prefork module:

#nano /etc/httpd/conf/httpd.conf
       < IfModule mpm_prefork_module>
       StartServers              4
       MinSpareServers          20
       MaxSpareServers          40
       MaxRequestWorkers       200
       MaxConnectionsPerChild 4500
      </IfModule >

 

To change the MPM in plain RHEL or Debian based systems replace mpm_prefork_module with mpm_worker_module or mpm_event_module, respectively.

In DirectAdmin the MPM module can be selected by using Custombuild or by editing /usr/local/directadmin/custombuild/options.conf

cPanel administrators can change the MPM by following WHM > Home > Software > EasyApache 4



3. MPM Directives

 

Below you may find links to the Apache documentation for all 3 MPM modules:

 

StartServers (Prefork, Event, Worker MPM)


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, unless you frequently restart your server and contains a large number of requests upon reboot.

Hint: Mirror this value to what is set in MinSpareServers.

 

MinSpareServers (Prefork MPM)


Sets the desired minimum number of idle child server processes. An idle process is one which is not handling a request, but waiting for a new request.

If there are fewer spareservers idle then specified by this value, then the parent process creates new children at a maximum rate of 1 per second. From Apache 2.4, this rate increases exponentially starting with 1 and ending with 32 children spawned per second.

The benefit is that when a request comes in it can take an idle thread; should a thread not be available, Apache would have to spawn a new child, taking up resources and extending the time it takes for the request to go through.

Woktron recommends adjusting the value for this setting as follows. These values are based on the total amount of memory (RAM) that is installed:

  • Virtual Private Server 5
  • Dedicated server with 1-2GB RAM 10
  • Dedicated server with 2-4GB RAM 20
  • Dedicated server with 4+ GB RAM 25

Setting this parameter to a high number is almost always a bad idea, unless it involves very busy websites.

 

MaxSpareServers (Prefork MPM)


Sets the desired maximum number of idle child server processes. An idle process is one which is not handling a request, but waiting for a new request.

If there are more than MaxSpareServers idle, then the parent process will kill off the excess processes. If there are more idle processes than this number, then they are terminated.

If the MaxSpareServers value is less than MinSpareServers, Apache will automatically adjust MaxSpareServers to equal MinSpareServers plus one.

Unless your website is extremely busy, this number should not be set too high, since idle processes consume valuable resources.

 

ServerLimit (Prefork, Event, Worker MPM)


In Prefork MPM The ServerLimit directive represents the upper limit of MaxRequestWorkers. This setting is generally used as a safeguard or ceiling against input errors when modifying MaxRequestWorkers.

With Prefork MPM ServerLimit is only used in case you need to set MaxRequestWorkers higher than 256 (default). In this case you should match the value you have set for MaxRequestWorkers, but you should not set the value of this directive any higher than what you might want to set MaxRequestWorkers to.

In Event MPM and Worker MPM ServerLimit represents the upper limit of children Apache is allowed. The cap prevents spawning vastly more children than a system can handle, resulting in downtime, or even data loss.

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.

 

ThreadLimit (Event, Worker MPM)


This directive sets the maximum configured value for ThreadsPerChild for the lifetime of the Apache httpd process. Any attempts to change this directive during a restart will be ignored, but ThreadsPerChild can be modified during a restart up to the value of this directive.

Special care must be taken when using this directive. If ThreadLimit is set to a value much higher than ThreadsPerChild, extra unused shared memory will be allocated. If both ThreadLimit and ThreadsPerChild are set to values higher than the system can handle, Apache httpd may not start or the system may become unstable.

Do not set the value of this directive any higher than your greatest predicted setting of ThreadsPerChild for the current run of Apache httpd.

 

ThreadsPerChild (Event, Worker MPM)


This directive sets the number of threads created by each child process. Every thread running can handle a single request. The child creates these threads at startup.

If using an MPM like mpm_winnt, where there is only one child process, this number should be high enough to handle the entire load of the server.

If using an MPM like worker, where there are multiple child processes, the total number of threads should be high enough to handle the common load on the server.

There is an upper limit on this directive as well, and the limit is controlled by the ThreadLimit directive, which defaults to 64 threads.

The adjustments to increase ThreadsPerChild past 64 threads also need to be made to ThreadLimit.

Increasing this value allows each child to handle more requests keeping memory consumption down while allowing a larger MaxRequestWorkers directive. A key benefit of running more threads within each child is shared memory cache access. Threads from one child cannot access caches from another child. Boosting the number of threads per child squeezes out more performance due to this sharing of cache data

The default value for ThreadsPerChild is 64 when used with mpm_winnt and 25 when used with Prefork, Event or Worker MPM. This works well in most cases and is a fair balance between children and threads.

 

MaxRequestWorkers / MaxClients (Prefork, Event, Worker MPM)


MaxRequestWorkers was called MaxClients before Apache version 2.3.13. However, the old name is still supported. It 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.

If this value is set too low, connections sent to queue eventually time-out; however, if this directive is set too high, it causes the memory to start swapping.

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.

MaxRequestWorkers and ServerLimit should have equal or near equal values with MaxRequestWorkers never exceeding ServerLimit. For servers under high load this value should be increased.

See below for more information on how to define the MaxRequestWorkers directive.

 

Formula to determine the MaxRequestWorkers directive:

 

I define Critical Services as services such as mySQL, Plesk, DirectAdmin; any service that is required for proper operation of your server.

I’ve used the following commands via shell to determine values for Total Memory, OS Memory, MySQL Memory, and Apache Process Size:

 

TOTAL MEMORY

[root@vps httpd]# free -m
total used free shared buffers cached Mem: 
1002 599 402 0 28 337
-/+ buffers/cache: 233 769
Swap: 2047 124 1922

MYSQL MEMORY

[root@vps httpd]# ps aux | grep ‘mysql’ | awk ‘{print $6}’
408
21440
704

APACHE PROCESS SIZE

[root@vps httpd]# ps aux | grep ‘httpd’ | awk ‘{print $6}’
22468
11552
41492
40868
41120
41696
39488
41704
15552
16076
16084
728

 

In this case the server has 1002Mb of memory allocated, xx used by the OS itself, 21Mb used by mySQL, and each Apache thread averages about 30Mb. MaxClients = (1002 – 21) / 30 therefore MaxClients = 32.7

 

The required values can also be determined with one single command

free -mps aux | grep 'mysql' | awk '{print $6}'ps aux | grep 'postgresql' | awk '{print $6}'ps aux | grep 'httpd' | awk '{print $6}'

 

MaxConnectionsPerChild (Prefork, Event, Worker MPM)


MaxConnectionsPerChild 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 process can consume by (accidental) memory leakage. Code executed through Apache may contain faults which leak memory. These leaks add up over time making less and less of the shared memory pool of the child usable. The way to recover from leaked memory is to recycle the affected Apache child process.

How to determine the best value for MaxConnectionsPerChild:

 

Formula to determine the MaxConnectionsPerChild directive:

 

Determining these values is a bit more complex as it requires some type of statistics package or thorough knowledge of interpreting Apache access logs.

This directive does not adversely effect memory usage, only a small amount of cpu time to cycle the process. Therefore, if you are unable to determine this information the default setting of 1000 should be used.



4. Core Apache Directives

 

The core directives for Apache can be edited in the files below:

On a DirectAdmin based server it will be located in: /etc/httpd/conf/extra/httpd-default.conf
On a cPanel server, it will be located in /etc/apache2/conf.d/httpd.conf
On a Plesk server, it will be in /etc/httpd/conf/

If you are using nano, vi or vim: once you open the file, you can find the directives by scrolling through the file. Using VI or VIM you can also search by typing forward-slash ‘/’ and typing the exact string that you are looking for (search is case specific).

 

Timeout


The Timeout setting is the number of seconds before data "sends" or "receives" (to or from the client) times out. The default value is set to 60 seconds.

Determining the ideal Timeout value depends on both traffic habits and hosted applications. Ideally, Timeout should be as low as possible while still allowing the vast majority of regular traffic to operate without issue.

Large timeouts force site visitors to "wait in line" which adds extra load to the server. It also opens the server to SlowLoris style DOS attacks and could cause a long wait in the browser when it does encounter a problem.

Low timeouts allow Apache to recover from errant stuck connections quickly. Lowering the Timeout value too much will cause a long running script to terminate earlier than expected.

It becomes necessary to strike a balance between the two extremes.

A reasonable value is 100-120 for Virtual Private Servers with limited resources, or heavily loaded dedicated servers. For servers under normal load a lower value, preferably below 60, is recommended.

 

KeepAlive


The KeepAlive directive can provide as much as a 50% reduction in latency, while providing a reduction in CPU usage. It helps significantly with boosting the performance of Apache. The default value is ON.

This performance boost is accomplished by enabling persistent connections on the web server. These persistent connections reuse the same initial connections a browser creates when connecting to Apache for all follow-up requests which occur within a short period.

KeepAlive should be set to On in most situations.

However, KeepAlive increases memory usage and should be disabled on servers that have only a limited amount of RAM available.

This is because Apache processes have to keep connections open waiting for new requests from established connections. While they are waiting they are occupying RAM that could be used to service other clients. If you turn off KeepAlive fewer apache processes will remain active.

You should also disable KeepAlive if you have bursty traffic where a lot of concurrent users access your sites during a short time period. KeepAlive will cause your RAM usage to skyrocket.

In short, Disabling KeepAlive will lower memory usage and allows Apache to serve more users, while enabling KeepAlive improves performance and decreases CPU load.

MaxKeepAliveRequests and KeepAliveTimeout. Discussed in the next section, play a vital role in fine-tuning the KeepAlive directive.

 

MaxKeepAliveRequests


This setting limits the number of requests allowed per persistent connection when KeepAlive is on. If it is set to 0, unlimited requests will be allowed. The default value is 100.

Generally, you want this value to be at least as high as the largest count of elements (HTML, Text, CSS, Images, Etc..) served by the most heavily trafficked pages on the server.

It is recommended to not increase this value beyond 100 for virtualized accounts like VPS accounts. On dedicated servers with ample of RAM it is possible for this value to be increased.

 

KeepAliveTimeout


The number of seconds Apache will wait for another request before closing the connection.

Setting this to a high value may cause performance problems in heavily loaded servers. The higher the timeout, the more server processes will be kept occupied waiting on connections with idle clients.

The default value of 10 seconds is a good value for average server performance. This value should be kept low as the socket will be idle for extended periods otherwise. It is recommended that this value be lowered to 5 on servers under heavy load.



5. Other Performance Improvements

Remove Unused Modules


Preserve memory by disabling unneeded modules from loading, including but not limited to mod_php, mod_ruby, mod_perl, etc. Remember, you can view what Apache modules have been compiled by entering httpd -l

 

Set ExtendedStatus Off


ExtendedStatus will produce several system calls for each request to gather statistics, which negatively impacts performance. When possible it is better to utilize ExtendedStatus for a set time period in order to benchmark, but then turn it back off.

 

Disable HostnameLookups


Avoid doing DNS lookups that always cost additional CPU time. You will rarely ever need HostnameLookups and when you do, you can look them up after the fact. If you have HostnameLookups off, avoid using hostname in configs as this will prevent you from having to wait for the DNS of the hostnames in your configs to resolve. You should use IP addresses instead.

 

Utilize mod_gzip/mod_deflate


Gzip your content before sending it off, which then the client will uncompress upon receipt. This will minimize the size of file transfers and will generally improve the user experience.

 

Avoid DirectoryIndex Wildcards


Select a specific DirectoryIndex, i.e. index.html or index.php, not index.

 

Use mod_disk_cache NOT mod_mem_cache


mod_mem_cache will not share its cache among different apache processes. This results in high memory usage with little performance gain, because mod_mem_cache will rarely serve the same page twice in the same apache process.

 

Instead, use mod_disk_cache with a flat hierarchy. Set values CacheDirLength=2 and CacheDirLevels=1 to ensure htcacheclean will not take forever when cleaning up your cache directory.

 

To utilize your cache you must also be sure to setup appropriate Expires, Etag, and Cache-Control Headers i.e. you must tell when a file expires, otherwise you will not experience any caching benefits.

 

Move Cache to external drive


Place your cache on a separate physical disk for fastest access without slowing down other processes. A Solid State Drive provides the fastest access times.



6. Testing and Restarting Apache

Be sure once you’ve saved the file to perform a configuration test before restarting Apache. This test parses the configuration files and either reports a Syntax Ok or it offers information about the particular syntax error.

 

To test your Apache configuration enter:

[root@vps httpd]# service httpd configtest
Syntax OK

Or:

[root@vps httpd]# apachectl -t
Syntax OK

 

To restart Apache enter:

[root@vps httpd]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

 

cPanel Only: More information about the correct procedure to edit your Apache configuration can be found here



7. Apache2Buddy

Apache2Buddy is a script similar to MySQLTuner, that reviews your Apache setup, and makes suggestions based on your Apache process memory and overall RAM. The apache2buddy.pl script will check for the following:

  • PHP memory limits
  • Memcache
  • MaxClients
  • Memory usage
  • Max potential memory usage
  • Percentage of total RAM allocated to Apache
  • MaxRequestWorkers

 

You can run the script with the following command:

curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | sudo perl

 

 

8. ApacheBench

Apache Bench (ab) is a load testing and benchmarking tool designed for Apache webserver installations (although, it will work without issue on any HTTP server such as nginx).

To install ab, run the following commands:

CentOS/Fedora

yum install httpd-tools

Debian/Ubuntu

apt-get update
apt-get install -y apache2-utils

 

Syntax

to benchmark your server, enter the command below, replacing yourdomain with your domain name.

ab -t 60 -n 20 -kc 5 http://yourdomain.com/

Running ApacheBench is similar to directing a denial-of-service attack towards your own server. This particular tool is not designed to be sympathetic to your infrastructure, and provides no ability to increase concurrency in measured intervals over a testing period.

The only option when running a load test through ab is to flood your web server with an arbitrary number of simultaneous requests all in one instant.

 

Optional Flags

  • -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: will dump each response's body and header to stdout so that you can identify success or failure.
  • -k: HTTP Keep-Alive

Keep in mind that if you’re using both the -t and the -n flags, -t should always go first

 

 

9. Other benchmarking tools

Some additional benchmarking tools for HTTP webservers are:

SIEGE

HTTP load test utility supported on UNIX. You can benchmark multiple URL’s by creating a text file to load test against.

Installation

yum install siege

syntax

siege -q -t 5S -c 500 http://yourdomain.com

 

Optional flags

  • -q: run quietly (not showing request details)
  • -t: run for 5 seconds
  • -c: 500 concurrent requests

 

Gobench

A load testing utility to benchmark web server performance written in Go language. It supports more than 20,000 concurrent users.

 

Apache JMeter

One of the most popular open source tools to measure web application performance. JMeter is a java based application. It not only supports webservers, but you can use it to benchmark the performance of PHP, Java. ASP.net, SOAP, REST, etc. .

 

wrk

With wrk, you can specify to run a load test with a number of threads.

syntax

wrk –t4 –c100 -d120s http://yourdomain.com

 

Optional flags

  • -d: test for 2 minutes (120 seconds)
  • -t: 4 threads
  • -c: 100 concurrent users

 

HTTPLoad

Httpload can read multiple URLs from text files, or you can specify it in the command argument. Httpload supports SSL/TLS encryption, meaning you have the ability to query HTTPS (SSL) enabled web pages.

syntax

httpload -cipher AES256-SHA -parallel 200 -seconds 120 URL_LIST.txt

 

httperf

syntax

httperf --server yourdomain.com --port 80 --num-conns 1000 --rate 100

 

  • dedicated servers, apache, optimize, mpm, keepalive
  • 109 Users Found This Useful
Was this answer helpful?

Related Articles

Installation of SpamAssassin on DirectAdmin

In this guide I will be explaining how to install and configure SpamAssasin on a Direct Admin...

Installation Clam Anti Virus (ClamAV) on DirectAdmin / CentOS

Clam AntiVirus is a popular open source (GPL) anti-virus toolkit for UNIX, designed for e-mail...

Installation Rootkit Hunter (rkhunter) on CentOS

  Rootkit Hunter (rkhunter) is a Unix-based tool that scans for rootkits, backdoors and possible...

How to recover from a broken RAID array with MDADM

This article will attempt to guide you to determine if a MDADM based raid array (in our case a...

How to install and configure Munin on CentOS

Munin surveys all your servers and remembers what it saw. It presents all the information in...