1 <?xml version="1.0" encoding="ISO-8859-1"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><!--
4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5 This file is generated from xml source: DO NOT EDIT
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8 <title>Performance Scaling
9 - Apache HTTP Server</title>
10 <link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
11 <link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
12 <link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="../style/css/prettify.css" />
13 <script src="../style/scripts/prettify.js" type="text/javascript">
16 <link href="../images/favicon.ico" rel="shortcut icon" /></head>
17 <body id="manual-page"><div id="page-header">
18 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
19 <p class="apache">Apache HTTP Server Version 2.5</p>
20 <img alt="" src="../images/feather.gif" /></div>
21 <div class="up"><a href="./"><img title="<-" alt="<-" src="../images/left.gif" /></a></div>
23 <a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.5</a></div><div id="page-content"><div id="preamble"><h1>Performance Scaling
26 <p><span>Available Languages: </span><a href="../en/misc/perf-scaling.html" title="English"> en </a></p>
30 <p>The Performance Tuning page in the Apache 1.3 documentation says:
33 <li>“Apache is a general webserver, which is designed to be
34 correct first, and fast
35 second. Even so, its performance is quite satisfactory. Most
36 sites have less than 10Mbits of outgoing bandwidth, which
37 Apache can fill using only a low end Pentium-based
41 <p>However, this sentence was written a few years ago, and in the
42 meantime several things have happened. On one hand, web server
43 hardware has become much faster. On the other hand, many sites now
44 are allowed much more than ten megabits per second of outgoing
45 bandwidth. In addition, web applications have become more complex.
46 The classic brochureware site is alive and well, but the web has
47 grown up substantially as a computing application platform and
48 webmasters may find themselves running dynamic content in Perl, PHP
49 or Java, all of which take a toll on performance.
51 <p>Therefore, in spite of strides forward in machine speed and
52 bandwidth allowances, web server performance and web application
53 performance remain areas of concern. In this documentation several
54 aspects of web server performance will be discussed.
58 <div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#what-will-and-will-not-be-discussed">What Will and Will Not Be Discussed
60 <li><img alt="" src="../images/down.gif" /> <a href="#monitoring-your-server">Monitoring Your Server
62 <li><img alt="" src="../images/down.gif" /> <a href="#configuring-for-performance">Configuring for Performance
64 <li><img alt="" src="../images/down.gif" /> <a href="#caching-content">Caching Content
66 <li><img alt="" src="../images/down.gif" /> <a href="#further-considerations">Further Considerations
68 </ul><ul class="seealso"><li><a href="#comments_section">Comments</a></li></ul></div>
69 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
71 <h2><a name="what-will-and-will-not-be-discussed" id="what-will-and-will-not-be-discussed">What Will and Will Not Be Discussed
74 <p>The session will focus on easily accessible configuration and tuning
75 options for Apache httpd 2.2 and 2.3 as well as monitoring tools.
76 Monitoring tools will allow you to observe your web server to
77 gather information about its performance, or lack thereof.
78 We'll assume that you don't have an unlimited budget for
79 server hardware, so the existing infrastructure will have to do the
80 job. You have no desire to compile your own Apache, or to recompile
81 the operating system kernel. We do assume, though, that you have
82 some familiarity with the Apache httpd configuration file.
85 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
87 <h2><a name="monitoring-your-server" id="monitoring-your-server">Monitoring Your Server
90 <p>The first task when sizing or performance-tuning your server is to
91 find out how your system is currently performing. By monitoring
92 your server under real-world load, or artificially generated load,
93 you can extrapolate its behavior under stress, such as when your
94 site is mentioned on Slashdot.
98 <h3><a name="monitoring-tools" id="monitoring-tools">Monitoring Tools
103 <h4><a name="top" id="top">top
106 <p>The top tool ships with Linux and FreeBSD. Solaris offers
107 `prstat'. It collects a number of statistics for the
108 system and for each running process, then displays them
109 interactively on your terminal. The data displayed is
110 refreshed every second and varies by platform, but
111 typically includes system load average, number of processes
112 and their current states, the percent CPU(s) time spent
113 executing user and system code, and the state of the
114 virtual memory system. The data displayed for each process
115 is typically configurable and includes its process name and
116 ID, priority and nice values, memory footprint, and
117 percentage CPU usage. The following example shows multiple
118 httpd processes (with MPM worker and event) running on an
122 <div class="example"><p><code>
123 top - 23:10:58 up 71 days, 6:14, 4 users, load average:
124 0.25, 0.53, 0.47<br />
125 Tasks: 163 total, 1 running, 162 sleeping, 0 stopped,
127 Cpu(s): 11.6%us, 0.7%sy, 0.0%ni, 87.3%id, 0.4%wa,
128 0.0%hi, 0.0%si, 0.0%st<br />
129 Mem: 2621656k total, 2178684k used, 442972k free,
130 100500k buffers<br />
131 Swap: 4194296k total, 860584k used, 3333712k free,
132 1157552k cached<br />
134 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+
136 16687 example_ 20 0 1200m 547m 179m S 45 21.4
137 1:09.59 httpd-worker<br />
138 15195 www 20 0 441m 33m 2468 S 0 1.3
139 0:41.41 httpd-worker<br />
140 1 root 20 0 10312 328 308 S 0 0.0 0:33.17
142 2 root 15 -5 0 0 0 S 0 0.0 0:00.00
144 3 root RT -5 0 0 0 S 0 0.0 0:00.14
146 4 root 15 -5 0 0 0 S 0 0.0 0:04.58
148 5 root RT -5 0 0 0 S 0 0.0 4:45.89
150 6 root 15 -5 0 0 0 S 0 0.0 1:42.52
152 7 root 15 -5 0 0 0 S 0 0.0 0:00.00
154 19 root 15 -5 0 0 0 S 0 0.0 0:00.00
156 20 root 15 -5 0 0 0 S 0 0.0 0:00.00
158 28 root RT -5 0 0 0 S 0 0.0 0:00.14
160 29 root 15 -5 0 0 0 S 0 0.0 0:00.20
162 30 root RT -5 0 0 0 S 0 0.0 0:05.96
164 31 root 15 -5 0 0 0 S 0 0.0 1:18.35
166 32 root RT -5 0 0 0 S 0 0.0 0:00.08
168 33 root 15 -5 0 0 0 S 0 0.0 0:00.18
170 34 root RT -5 0 0 0 S 0 0.0 0:06.00
172 35 root 15 -5 0 0 0 S 0 0.0 1:08.39
174 36 root RT -5 0 0 0 S 0 0.0 0:00.10
176 37 root 15 -5 0 0 0 S 0 0.0 0:00.16
178 38 root RT -5 0 0 0 S 0 0.0 0:06.08
180 39 root 15 -5 0 0 0 S 0 0.0 1:22.81
182 68 root 15 -5 0 0 0 S 0 0.0 0:06.28
184 69 root 15 -5 0 0 0 S 0 0.0 0:00.04
186 70 root 15 -5 0 0 0 S 0 0.0 0:00.04
190 <p>Top is a wonderful tool even though it’s slightly resource
191 intensive (when running, its own process is usually in the
192 top ten CPU gluttons). It is indispensable in determining
193 the size of a running process, which comes in handy when
194 determining how many server processes you can run on your
195 machine. How to do this is described in '<a href="/httpd/PerformanceScalingUp#S">
198 '. Top is, however, an interactive tool and running it
199 continuously has few if any advantages.
202 <h4><a name="free" id="free">free
205 <p>This command is only available on Linux. It shows how much
206 memory and swap space is in use. Linux allocates unused
207 memory as file system cache. The free command shows usage
208 both with and without this cache. The free command can be
209 used to find out how much memory the operating system is
210 using, as described in the paragraph '<a href="/httpd/PerformanceScalingUp#S">
213 '. The output of free looks like this:
216 <div class="example"><p><code>
217 sctemme@brutus:~$ free<br />
218 total used free shared buffers cached<br />
219 Mem: 4026028 3901892 124136 0 253144
221 -/+ buffers/cache: 2807704 1218324<br />
222 Swap: 3903784 12540 3891244
226 <h4><a name="vmstat" id="vmstat">vmstat
229 <p>This command is available on many unix platforms. It
230 displays a large number of operating system metrics. Run
231 without argument, it displays a status line for that
232 moment. When a numeric argument is added, the status is
233 redisplayed at designated intervals. For example, <code>
236 causes the information to reappear every five seconds.
237 Vmstat displays the amount of virtual memory in use, how
238 much memory is swapped in and out each second, the number
239 of processes currently running and sleeping, the number of
240 interrupts and context switches per second and the usage
241 percentages of the CPU.
244 The following is <code>vmstat
246 output of an idle server:
250 <div class="example"><p><code>
251 [sctemme@GayDeceiver sctemme]$ vmstat 5 3<br />
254 r b w swpd free buff cache si so bi bo in
256 0 0 0 0 186252 6688 37516 0 0 12 5 47
258 0 0 0 0 186244 6696 37516 0 0 0 16 41
260 0 0 0 0 186236 6704 37516 0 0 0 9 44
264 <p>And this is output of a server that is under a load of one
265 hundred simultaneous connections fetching static content:
268 <div class="example"><p><code>
269 sctemme@GayDeceiver sctemme]$ vmstat 5 3<br />
272 r b w swpd free buff cache si so bi bo in
274 1 0 1 0 162580 6848 40056 0 0 11 5 150
276 6 0 1 0 163280 6856 40248 0 0 0 66 6384
278 11 0 0 0 162780 6864 40436 0 0 0 61 6309
282 <p>The first line gives averages since the last reboot. The
283 subsequent lines give information for five second
284 intervals. The second argument tells vmstat to generate
285 three reports and then exit.
290 <h4><a name="se-toolkit" id="se-toolkit">SE Toolkit
293 <p>The SE Toolkit is a system monitoring toolkit for Solaris.
294 Its programming language is based on the C preprocessor and
295 comes with a number of sample scripts. It can use both the
296 command line and the GUI to display information. It can
297 also be programmed to apply rules to the system data. The
298 example script shown in Figure 2, Zoom.se, shows green,
299 orange or red indicators when utilization of various parts
300 of the system rises above certain thresholds. Another
301 included script, Virtual Adrian, applies performance tuning
302 metrics according to.
304 <p>The SE Toolkit has drifted around for a while and has had
305 several owners since its inception. It seems that it has
306 now found a final home at Sunfreeware.com, where it can be
307 downloaded at no charge. There is a single package for
308 Solaris 8, 9 and 10 on SPARC and x86, and includes source
309 code. SE Toolkit author Richard Pettit has started a new
310 company, Captive Metrics4 that plans to bring to market a
311 multiplatform monitoring tool built on the same principles
312 as SE Toolkit, written in Java.
317 <h4><a name="dtrace" id="dtrace">DTrace
320 <p>Given that DTrace is available for Solaris, FreeBSD and OS
321 X, it might be worth exploring it. There's also
322 mod_dtrace available for httpd.
327 <h4><a name="mod_status" id="mod_status">mod_status
330 <p>The mod_status module gives an overview of the server
331 performance at a given moment. It generates an HTML page
332 with, among others, the number of Apache processes running
333 and how many bytes each has served, and the CPU load caused
334 by httpd and the rest of the system. The Apache Software
335 Foundation uses mod_status on its own <a href="http://apache.org/server-status">
338 .If you put the <code>ExtendedStatus On
340 directive in your <code>httpd.conf
342 ,the <code>mod_status
344 page will give you more information at the cost of a little
345 extra work per request.
351 <h3><a name="web-server-log-files" id="web-server-log-files">Web Server Log Files
354 <p>Monitoring and analyzing the log files httpd writes is one of
355 the most effective ways to keep track of your server health and
356 performance. Monitoring the error log allows you to detect
357 error conditions, discover attacks and find performance issues.
358 Analyzing the access logs tells you how busy your server is,
359 which resources are the most popular and where your users come
360 from. Historical log file data can give you invaluable insight
361 into trends in access to your server, which allows you to
362 predict when your performance needs will overtake your server
367 <h4><a name="ErrorLog" id="ErrorLog">Error Log
370 <p>The error log will contain messages if the server has
371 reached the maximum number of active processes or the
372 maximum number of concurrently open files. The error log
373 also reflects when processes are being spawned at a
374 higher-than-usual rate in response to a sudden increase in
375 load. When the server starts, the stderr file descriptor is
376 redirected to the error logfile, so any error encountered
377 by httpd after it opens its logfiles will appear in this
378 log. This makes it good practice to review the error log
381 <p>Before Apache httpd opens its logfiles, any errors will be
382 written to the stderr stream. If you start httpd manually,
383 this error information will appear on your terminal and you
384 can use it directly to troubleshoot your server. If your
385 httpd is started by a startup script, the destination of
386 early error messages depends on their design. The <code>
389 file is usually a good bet. On Windows, early error
390 messages are written to the Applications Event Log, which
391 can be viewed through the Event Viewer in Administrative
395 The Error Log is configured through the <code>ErrorLog
399 configuration directives. The error log of httpd’s main
400 server configuration receives the log messages that pertain
401 to the entire server: startup, shutdown, crashes, excessive
402 process spawns, etc. The <code>ErrorLog
404 directive can also be used in virtual host containers. The
405 error log of a virtual host receives only log messages
406 specific to that virtual host, such as authentication
407 failures and 'File not Found' errors.
409 <p>On a server that is visible to the Internet, expect to see a
410 lot of exploit attempt and worm attacks in the error log. A
411 lot of these will be targeted at other server platforms
412 instead of Apache, but the current state of affairs is that
413 attack scripts just throw everything they have at any open
414 port, regardless of which server is actually running or
415 what applications might be installed. You could block these
416 attempts using a firewall or <a href="http://www.modsecurity.org/">
419 ,but this falls outside the scope of this discussion.
424 directive determines the level of detail included in the
425 logs. There are eight log levels as described here:
448 <p> Emergencies - system is unusable.
458 <p> Action must be taken immediately.
468 <p> Critical Conditions.
478 <p> Error conditions.
488 <p> Warning conditions.
498 <p> Normal but significant condition.
518 <p> Debug-level messages
523 <p>The default log level is warn. A production server should
524 not be run on debug, but increasing the level of detail in
525 the error log can be useful during troubleshooting.
526 Starting with 2.3.8 <code>LogLevel
528 can be specified on a per module basis:
531 <div class="example"><p><code>
532 LogLevel debug mod_ssl:warn
536 This puts all of the server in debug mode, except for <code>
539 ,which tends to be very noisy.
544 <h4><a name="AccessLog" id="AccessLog">Access Log
547 <p>Apache httpd keeps track of every request it services in its
548 access log file. In addition to the time and nature of a
549 request, httpd can log the client IP address, date and time
550 of the request, the result and a host of other information.
551 The various logging format features are documented in the <a href="http://httpd.apache.org/docs/current/mod/core.html#loglevel">
554 .This file exists by default for the main server and can be
555 configured per virtual host by using the <code>TransferLog
559 configuration directive.
561 <p>The access logs can be analyzed with any of several free and
562 commercially available programs. Popular free analysis
563 packages include Analog and Webalizer. Log analysis should
564 be done offline so the web server machine is not burdened
565 by processing the log files. Most log analysis packages
566 understand the Common Log Format. The fields in the log
567 lines are explained in in the following:
571 <div class="example"><p><code>
572 195.54.228.42 - - [24/Mar/2007:23:05:11 -0400] "GET
573 /sander/feed/ HTTP/1.1" 200 9747<br />
574 64.34.165.214 - - [24/Mar/2007:23:10:11 -0400] "GET
575 /sander/feed/atom HTTP/1.1" 200 9068<br />
576 60.28.164.72 - - [24/Mar/2007:23:11:41 -0400] "GET /
577 HTTP/1.0" 200 618<br />
578 85.140.155.56 - - [24/Mar/2007:23:14:12 -0400] "GET
579 /sander/2006/09/27/44/ HTTP/1.1" 200 14172<br />
580 85.140.155.56 - - [24/Mar/2007:23:14:15 -0400] "GET
581 /sander/2006/09/21/gore-tax-pollution/ HTTP/1.1" 200 15147<br />
582 74.6.72.187 - - [24/Mar/2007:23:18:11 -0400] "GET
583 /sander/2006/09/27/44/ HTTP/1.0" 200 14172<br />
584 74.6.72.229 - - [24/Mar/2007:23:24:22 -0400] "GET
585 /sander/2006/11/21/os-java/ HTTP/1.0" 200 13457
619 <p> IP address where the request originated
633 <p> Remote user identity as reported by their
648 <p> Remote username as authenticated by Apache
658 <p> [24/Mar/2007:23:05:11 -0400]
662 <p> Date and time of request
672 <p> "GET /sander/feed/ HTTP/1.1"
704 <p> Bytes transferred w/o headers
711 <h4><a name="rotating-log-files" id="rotating-log-files">Rotating Log Files
714 <p>There are several reasons to rotate logfiles. Even though
715 almost no operating systems out there have a hard file size
716 limit of two Gigabytes anymore, log files simply become too
717 large to handle over time. Additionally, any periodic log
718 file analysis should not be performed on files to which the
719 server is actively writing. Periodic logfile rotation helps
720 keep the analysis job manageable, and allows you to keep a
721 closer eye on usage trends.
723 <p>On unix systems, you can simply rotate logfiles by giving
724 the old file a new name using mv. The server will keep
725 writing to the open file even though it has a new name.
726 When you send a graceful restart signal to the server, it
727 will open a new logfile with the configured name. For
728 example, you could run a script from cron like this:
732 <div class="example"><p><code>
733 APACHE=/usr/local/apache2<br />
734 HTTPD=$APACHE/bin/httpd<br />
735 mv $APACHE/logs/access_log
736 $APACHE/logarchive/access_log-‘date +%F‘<br />
740 <p>This approach also works on Windows, just not as smoothly.
741 While the httpd process on your Windows server will keep
742 writing to the log file after it has been renamed, the
743 Windows Service that runs Apache can not do a graceful
744 restart. Restarting a Service on Windows means stopping it
745 and then starting it again. The advantage of a graceful
746 restart is that the httpd child processes get to complete
747 responding to their current requests before they exit.
748 Meanwhile, the httpd server becomes immediately available
749 again to serve new requests. The stop-start that the
750 Windows Service has to perform will interrupt any requests
751 currently in progress, and the server is unavailable until
752 it is started again. Plan for this when you decide the
753 timing of your restarts.
756 A second approach is to use piped logs. From the <code>
763 directives you can send the log data into any program using
764 a pipe character (<code>|
769 <div class="example"><p><code>CustomLog "|/usr/local/apache2/bin/rotatelogs
770 /var/log/access_log 86400" common
773 <p>The program on the other end of the pipe will receive the
774 Apache log data on its stdin stream, and can do with this
775 data whatever it wants. The rotatelogs program that comes
776 with Apache seamlessly turns over the log file based on
777 time elapsed or the amount of data written, and leaves the
778 old log files with a timestamp suffix to its name. This
779 method for rotating logfiles works well on unix platforms,
780 but is currently broken on Windows.
785 <h4><a name="logging-and-performance" id="logging-and-performance">Logging and Performance
788 <p>Writing entries to the Apache log files obviously takes some
789 effort, but the information gathered from the logs is so
790 valuable that under normal circumstances logging should not
791 be turned off. For optimal performance, you should put your
792 disk-based site content on a different physical disk than
793 the server log files: the access patterns are very
794 different. Retrieving content from disk is a read operation
795 in a fairly random pattern, and log files are written to
799 Do not run a production server with your error <code>
802 set to debug. This log level causes a vast amount of
803 information to be written to the error log, including, in
804 the case of SSL access, complete dumps of BIO read and
805 write operations. The performance implications are
806 significant: use the default warn level instead.
808 <p>If your server has more than one virtual host, you may give
809 each virtual host a separate access logfile. This makes it
810 easier to analyze the logfile later. However, if your
811 server has many virtual hosts, all the open logfiles put a
812 resource burden on your system, and it may be preferable to
813 log to a single file. Use the <code>%v</code>
814 format character at the start of your <code class="directive"><a href="../mod/mod_log_config.html#logformat">LogFormat</a></code>
815 and starting 2.3.8 of your <code class="directive"><a href="../mod/core.html#errorlog">ErrorLog</a></code>
816 to make httpd print the hostname of the virtual host that
817 received the request or the error at the beginning of each
818 log line. A simple Perl script can split out the log file
819 after it rotates: one is included with the Apache source
820 under <code>support/split-logfile</code>.
823 You can use the <code>BufferedLogs
825 directive to have Apache collect several log lines in
826 memory before writing them to disk. This might yield better
827 performance, but could affect the order in which the
828 server's log is written.
834 <h3><a name="generating-a-test-load" id="generating-a-test-load">Generating A Test Load
837 <p>It is useful to generate a test load to monitor system
838 performance under realistic operating circumstances. Besides
839 commercial packages such as <a href="http://learnloadrunner.com/">LoadRunner</a>
840 ,there are a number of freely available tools to generate a
841 test load against your web server.
844 <li>Apache ships with a test program called ab, short for
845 Apache Bench. It can generate a web server load by
846 repeatedly asking for the same file in rapid succession.
847 You can specify a number of concurrent connections and have
848 the program run for either a given amount of time or a
849 specified number of requests.
851 <li>Another freely available load generator is http load11 .
852 This program works with a URL file and can be compiled with
855 <li>The Apache Software Foundation offers a tool named flood12
856 . Flood is a fairly sophisticated program that is
857 configured through an XML file.
859 <li>Finally, JMeter13 , a Jakarta subproject, is an all-Java
860 load-testing tool. While early versions of this application
861 were slow and difficult to use, the current version 2.1.1
862 seems to be versatile and useful.
865 <p>ASF external projects, that have proven to be quite
866 good: grinder, httperf, tsung, <a href="http://funkload.nuxeo.org/">FunkLoad</a>
870 <p>When you load-test your web server, please keep in mind that if
871 that server is in production, the test load may negatively
872 affect the server’s response. Also, any data traffic you
873 generate may be charged against your monthly traffic allowance.
878 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
879 <div class="section">
880 <h2><a name="configuring-for-performance" id="configuring-for-performance">Configuring for Performance
885 <h3><a name="apache-configuration" id="apache-configuration">Apache Configuration
888 <p>The Apache 2.2 httpd is by default a pre-forking web server.
889 When the server starts, the parent process spawns a number of
890 child processes that do the actual work of servicing requests.
891 But Apache httpd 2.0 introduced the concept of the
892 Multi-Processing Module (MPM). Developers can write MPMs to
893 suit the process- or threadingarchitecture of their specific
894 operating system. Apache 2 comes with special MPMs for Windows,
895 OS/2, Netware and BeOS. On unix-like platforms, the two most
896 popular MPMs are Prefork and Worker. The Prefork MPM offers the
897 same pre-forking process model that Apache 1.3 uses. The Worker
898 MPM runs a smaller number of child processes, and spawns
899 multiple request handling threads within each child process. In
900 2.3+ MPMs are no longer hard-wired. They too can be exchanged
901 via <code class="directive"><a href="../mod/core.html#loadmodule">LoadModule</a></code>.
902 The default MPM in 2.3 is the event MPM.
904 <p>The maximum number of workers, be they pre-forked child
905 processes or threads within a process, is an indication of how
906 many requests your server can manage concurrently. It is merely
907 a rough estimate because the kernel can queue connection
908 attempts for your web server. When your site becomes busy and
909 the maximum number of workers is running, the machine
910 doesn't hit a hard limit beyond which clients will be
911 denied access. However, once requests start backing up, system
912 performance is likely to degrade.
916 <h4><a name="MaxClients" id="MaxClients">MaxClients
922 directive in your Apache httpd configuration file specifies
923 the maximum number of workers your server can create. It
924 has two related directives, <code>MinSpareServers
926 and <code>MaxSpareServers
928 ,which specify the number of workers Apache keeps waiting
929 in the wings ready to serve requests. The absolute maximum
930 number of processes is configurable through the <code>
938 <h4><a name="spinning-threads" id="spinning-threads">Spinning Threads
941 <p>For the prefork MPM of the above directives are all there is
942 to determining the process limit. However, if you are
943 running a threaded MPM the situation is a little more
944 complicated. Threaded MPMs support the <code>
947 directive1 . Apache requires that <code>MaxClients
949 is evenly divisible by <code>ThreadsPerChild
951 .If you set either directive to a number that doesn’t
952 meet this requirement, Apache will send a message of
953 complaint to the error log and adjust the <code>
956 value downwards until it is an even factor of <code>
964 <h4><a name="sizing-maxClients" id="sizing-maxClients">Sizing MaxClients
967 <p>Optimally, the maximum number of processes should be set so
968 that all the memory on your system is used, but no more. If
969 your system gets so overloaded that it needs to heavily
970 swap core memory out to disk, performance will degrade
971 quickly. The formula for determining <code>MaxClients
976 <div class="example"><p><code>
977 total RAM − RAM for OS − RAM for external programs<br />
979 -------------------------------------------------------<br />
980 RAM per httpd process
983 <p>The various amounts of memory allocated for the OS, external
984 programs and the httpd processes is best determined by
985 observation: use the top and free commands described above
986 to determine the memory footprint of the OS without the web
987 server running. You can also determine the footprint of a
988 typical web server process from top: most top
989 implementations have a Resident Size (RSS) column and a
990 Shared Memory column.
992 <p>The difference between these two is the amount of memory
993 per-process. The shared segment really exists only once and
994 is used for the code and libraries loaded and the dynamic
995 inter-process tally, or 'scoreboard,' that Apache
996 keeps. How much memory each process takes for itself
997 depends heavily on the number and kind of modules you use.
998 The best approach to use in determining this need is to
999 generate a typical test load against your web site and see
1000 how large the httpd processes become.
1002 <p>The RAM for external programs parameter is intended mostly
1003 for CGI programs and scripts that run outside the web
1004 server process. However, if you have a Java virtual machine
1005 running Tomcat on the same box it will need a significant
1006 amount of memory as well. The above assessment should give
1007 you an idea how far you can push <code>MaxClients
1009 ,but it is not an exact science. When in doubt, be
1010 conservative and use a low <code>MaxClients
1012 value. The Linux kernel will put extra memory to good use
1013 for caching disk access. On Solaris you need enough
1014 available real RAM memory to create any process. If no real
1015 memory is available, httpd will start writing ‘No space
1016 left on device’ messages to the error log and be unable
1017 to fork additional child processes, so a higher <code>
1020 value may actually be a disadvantage.
1025 <h4><a name="selecting-your-mpm" id="selecting-your-mpm">Selecting your MPM
1028 <p>The prime reason for selecting a threaded MPM is that
1029 threads consume fewer system resources than processes, and
1030 it takes less effort for the system to switch between
1031 threads. This is more true for some operating systems than
1032 for others. On systems like Solaris and AIX, manipulating
1033 processes is relatively expensive in terms of system
1034 resources. On these systems, running a threaded MPM makes
1035 sense. On Linux, the threading implementation actually uses
1036 one process for each thread. Linux processes are relatively
1037 lightweight, but it means that a threaded MPM offers less
1038 of a performance advantage than in other environments.
1040 <p>Running a threaded MPM can cause stability problems in some
1041 situations For instance, should a child process of a
1042 preforked MPM crash, at most one client connection is
1043 affected. However, if a threaded child crashes, all the
1044 threads in that process disappear, which means all the
1045 clients currently being served by that process will see
1046 their connection aborted. Additionally, there may be
1047 so-called "thread-safety" issues, especially with
1048 third-party libraries. In threaded applications, threads
1049 may access the same variables indiscriminately, not knowing
1050 whether a variable may have been changed by another thread.
1052 <p>This has been a sore point within the PHP community. The PHP
1053 processor heavily relies on third-party libraries and
1054 cannot guarantee that all of these are thread-safe. The
1055 good news is that if you are running Apache on Linux, you
1056 can run PHP in the preforked MPM without fear of losing too
1057 much performance relative to the threaded option.
1062 <h4><a name="spinning-locks" id="spinning-locks">Spinning Locks
1065 <p>Apache httpd maintains an inter-process lock around its
1066 network listener. For all practical purposes, this means
1067 that only one httpd child process can receive a request at
1068 any given time. The other processes are either servicing
1069 requests already received or are 'camping out' on
1070 the lock, waiting for the network listener to become
1071 available. This process is best visualized as a revolving
1072 door, with only one process allowed in the door at any
1073 time. On a heavily loaded web server with requests arriving
1074 constantly, the door spins quickly and requests are
1075 accepted at a steady rate. On a lightly loaded web server,
1076 the process that currently "holds" the lock may
1077 have to stay in the door for a while, during which all the
1078 other processes sit idle, waiting to acquire the lock. At
1079 this time, the parent process may decide to terminate some
1080 children based on its <code>MaxSpareServers
1087 <h4><a name="the-thundering-herd" id="the-thundering-herd">The Thundering Herd
1090 <p>The function of the 'accept mutex' (as this
1091 inter-process lock is called) is to keep request reception
1092 moving along in an orderly fashion. If the lock is absent,
1093 the server may exhibit the Thundering Herd syndrome.
1095 <p>Consider an American Football team poised on the line of
1096 scrimmage. If the football players were Apache processes
1097 all team members would go for the ball simultaneously at
1098 the snap. One process would get it, and all the others
1099 would have to lumber back to the line for the next snap. In
1100 this metaphor, the accept mutex acts as the quarterback,
1101 delivering the connection "ball" to the
1102 appropriate player process.
1104 <p>Moving this much information around is obviously a lot of
1105 work, and, like a smart person, a smart web server tries to
1106 avoid it whenever possible. Hence the revolving door
1107 construction. In recent years, many operating systems,
1108 including Linux and Solaris, have put code in place to
1109 prevent the Thundering Herd syndrome. Apache recognizes
1110 this and if you run with just one network listener, meaning
1111 one virtual host or just the main server, Apache will
1112 refrain from using an accept mutex. If you run with
1113 multiple listeners (for instance because you have a virtual
1114 host serving SSL requests), it will activate the accept
1115 mutex to avoid internal conflicts.
1118 You can manipulate the accept mutex with the <code>
1121 directive. Besides turning the accept mutex off, you can
1122 select the locking mechanism. Common locking mechanisms
1123 include fcntl, System V Semaphores and pthread locking. Not
1124 all are available on every platform, and their availability
1125 also depends on compile-time settings. The various locking
1126 mechanisms may place specific demands on system resources:
1127 manipulate them with care.
1129 <p>There is no compelling reason to disable the accept mutex.
1130 Apache automatically recognizes the single listener
1131 situation described above and knows if it is safe to run
1132 without mutex on your platform.
1138 <h3><a name="tuning-the-operating-system" id="tuning-the-operating-system">Tuning the Operating System
1141 <p>People often look for the 'magic tune-up' that will
1142 make their system perform four times as fast by tweaking just
1143 one little setting. The truth is, present-day UNIX derivatives
1144 are pretty well adjusted straight out of the box and there is
1145 not a lot that needs to be done to make them perform optimally.
1146 However, there are a few things that an administrator can do to
1147 improve performance.
1151 <h4><a name="ram-and-swap-space" id="ram-and-swap-space">RAM and Swap Space
1154 <p>The usual mantra regarding RAM is "more is
1155 better". As discussed above, unused RAM is put to good
1156 use as file system cache. The Apache processes get bigger
1157 if you load more modules, especially if you use modules
1158 that generate dynamic page content within the processes,
1159 like PHP and mod_perl. A large configuration file-with many
1160 virtual hosts-also tends to inflate the process footprint.
1161 Having ample RAM allows you to run Apache with more child
1162 processes, which allows the server to process more
1163 concurrent requests.
1165 <p>While the various platforms treat their virtual memory in
1166 different ways, it is never a good idea to run with less
1167 disk-based swap space than RAM. The virtual memory system
1168 is designed to provide a fallback for RAM, but when you
1169 don't have disk space available and run out of
1170 swappable memory, your machine grinds to a halt. This can
1171 crash your box, requiring a physical reboot for which your
1172 hosting facility may charge you.
1174 <p>Also, such an outage naturally occurs when you least want
1175 it: when the world has found your website and is beating a
1176 path to your door. If you have enough disk-based swap space
1177 available and the machine gets overloaded, it may get very,
1178 very slow as the system needs to swap memory pages to disk
1179 and back, but when the load decreases the system should
1180 recover. Remember, you still have <code>MaxClients
1182 to keep things in hand.
1184 <p>Most unix-like operating systems use designated disk
1185 partitions for swap space. When a system starts up it finds
1186 all swap partitions on the disk(s), by partition type or
1187 because they are listed in the file <code>/etc/fstab
1189 ,and automatically enables them. When adding a disk or
1190 installing the operating system, be sure to allocate enough
1191 swap space to accommodate eventual RAM upgrades.
1192 Reassigning disk space on a running system is a cumbersome
1195 <p>Plan for available hard drive swap space of at least twice
1196 your amount of RAM, perhaps up to four times in situations
1197 with frequent peaking loads. Remember to adjust this
1198 configuration whenever you upgrade RAM on your system. In a
1199 pinch, you can use a regular file as swap space. For
1200 instructions on how to do this, see the manual pages for
1212 <h4><a name="ulimit-files-and-processes" id="ulimit-files-and-processes">ulimit: Files and Processes
1215 <p>Given a machine with plenty of RAM and processor capacity,
1216 you can run hundreds of Apache processes if necessary. . .
1217 and if your kernel allows it.
1219 <p>Consider a situation in which several hundred web servers
1220 are running; if some of these need to spawn CGI processes,
1221 the maximum number of processes would occur quickly.
1223 <p>However, you can change this limit with the command
1226 <div class="example"><p><code>
1227 ulimit [-H|-S] -u [newvalue]
1230 <p>This must be changed before starting the server, since the
1231 new value will only be available to the current shell and
1232 programs started from it. In newer Linux kernels the
1233 default has been raised to 2048. On FreeBSD, the number
1234 seems to be the rather unusual 513. In the default user
1235 shell on this system, <code>csh
1237 the equivalent is <code>limit
1239 and works analogous the the Bourne-like <code>ulimit
1244 <div class="example"><p><code>
1245 limit [-h] maxproc [newvalue]
1248 <p>Similarly, the kernel may limit the number of open files per
1249 process. This is generally not a problem for pre-forked
1250 servers, which just handle one request at a time per
1251 process. Threaded servers, however, serve many requests per
1252 process and much more easily run out of available file
1253 descriptors. You can increase the maximum number of open
1254 files per process by running the
1257 <div class="example"><p><code>ulimit -n [newvalue]
1260 <p>command. Once again, this must be done prior to starting
1266 <h4><a name="setting-user-limits-on-system-startup" id="setting-user-limits-on-system-startup">Setting User Limits on System Startup
1269 <p>Under Linux, you can set the ulimit parameters on bootup by
1270 editing the <code>/etc/security/limits.conf
1272 file. This file allows you to set soft and hard limits on a
1273 per-user or per-group basis; the file contains commentary
1274 explaining the options. To enable this, make sure that the
1275 file <code>/etc/pam.d/login
1280 <div class="example"><p><code>session required /lib/security/pam_limits.so
1283 <p>All items can have a 'soft' and a 'hard'
1284 limit: the first is the default setting and the second the
1285 maximum value for that item.
1288 In FreeBSD's <code>/etc/login.conf
1290 these resources can be limited or extended system wide,
1291 analogously to <code>limits.conf
1293 .'Soft' limits can be specified with <code>-cur
1295 and 'hard' limits with <code>-max
1299 <p>Solaris has a similar mechanism for manipulating limit
1300 values at boot time: In <code>/etc/system
1302 you can set kernel tunables valid for the entire system at
1303 boot time. These are the same tunables that can be set with
1306 kernel debugger during run time. The soft and hard limit
1307 corresponding to ulimit -u can be set via:
1310 <div class="example"><p><code>
1311 set rlim_fd_max=65536<br />
1312 set rlim_fd_cur=2048
1315 <p>Solaris calculates the maximum number of allowed processes
1316 per user (<code>maxuprc
1318 )based on the total amount available memory on the system (<code>
1321 ). You can review the numbers with
1324 <div class="example"><p><code>sysdef -i | grep maximum
1327 <p>but it is not recommended to change them.
1332 <h4><a name="turn-off-unused-services-and-modules" id="turn-off-unused-services-and-modules">Turn Off Unused Services and Modules
1335 <p>Many UNIX and Linux distributions come with a slew of
1336 services turned on by default. You probably need few of
1337 them. For example, your web server does not need to be
1338 running sendmail, nor is it likely to be an NFS server,
1341 <p>On Red Hat Linux, the chkconfig tool will help you do this
1342 from the command line. On Solaris systems <code>svcs
1346 will show which services are enabled and disable them
1349 <p>In a similar fashion, cast a critical eye on the Apache
1350 modules you load. Most binary distributions of Apache
1351 httpd, and pre-installed versions that come with Linux
1352 distributions, have their modules enabled through the <code>
1357 <p>Unused modules may be culled: if you don't rely on
1358 their functionality and configuration directives, you can
1359 turn them off by commenting out the corresponding <code>
1362 lines. Read the documentation on each module’s
1363 functionality before deciding whether to keep it enabled.
1364 While the performance overhead of an unused module is
1365 small, it's also unnecessary.
1371 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
1372 <div class="section">
1373 <h2><a name="caching-content" id="caching-content">Caching Content
1376 <p>Requests for dynamically generated content usually take
1377 significantly more resources than requests for static content.
1378 Static content consists of simple filespages, images, etc.-on disk
1379 that are very efficiently served. Many operating systems also
1380 automatically cache the contents of frequently accessed files in
1383 <p>Processing dynamic requests, on the contrary, can be much more
1384 involved. Running CGI scripts, handing off requests to an external
1385 application server and accessing database content can introduce
1386 significant latency and processing load to a busy web server. Under
1387 many circumstances, performance can be improved by turning popular
1388 dynamic requests into static requests. In this section, two
1389 approaches to this will be discussed.
1393 <h3><a name="making-popular-pages-static" id="making-popular-pages-static">Making Popular Pages Static
1396 <p>By pre-rendering the response pages for the most popular queries
1397 in your application, you can gain a significant performance
1398 improvement without giving up the flexibility of dynamically
1399 generated content. For instance, if your application is a
1400 flower delivery service, you would probably want to pre-render
1401 your catalog pages for red roses during the weeks leading up to
1402 Valentine's Day. When the user searches for red roses,
1403 they are served the pre-rendered page. Queries for, say, yellow
1404 roses will be generated directly from the database. The
1405 mod_rewrite module included with Apache is a great tool to
1406 implement these substitutions.
1410 <h4><a name="example-a-statically-rendered-blog" id="example-a-statically-rendered-blog">Example: A Statically Rendered Blog
1414 <strong>'we should provide a more useful example here.
1415 One showing how to make Wordpress or Drupal suck less.
1419 <p>Blosxom is a lightweight web log package that runs as a CGI.
1420 It is written in Perl and uses plain text files for entry
1421 input. Besides running as CGI, Blosxom can be run from the
1422 command line to pre-render blog pages. Pre-rendering pages
1423 to static HTML can yield a significant performance boost in
1424 the event that large numbers of people actually start
1427 <p>To run blosxom for static page generation, edit the CGI
1428 script according to the documentation. Set the $static dir
1429 variable to the <code>DocumentRoot
1431 of the web server, and run the script from the command line
1435 <div class="example"><p><code>$ perl blosxom.cgi -password='whateveryourpassword'
1438 <p>This can be run periodically from Cron, after you upload
1439 content, etc. To make Apache substitute the statically
1440 rendered pages for the dynamic content, we’ll use
1441 mod_rewrite. This module is included with the Apache source
1442 code, but is not compiled by default. It can be built with
1443 the server by passing the option <code>
1444 --enable-rewrite[=shared]
1446 to the configure command. Many binary distributions of
1447 Apache come with mod_rewrite included. The following is an
1448 example of an Apache virtual host that takes advantage of
1449 pre-rendered blog pages:
1452 <div class="example"><p><code>Listen *:8001<br />
1453 <VirtualHost *:8001><br />
1454 <span class="indent">
1455 ServerName blog.sandla.org:8001<br />
1456 ServerAdmin sander@temme.net<br />
1457 DocumentRoot "/home/sctemme/inst/blog/httpd/htdocs"<br />
1459 "/home/sctemme/inst/blog/httpd/htdocs"><br />
1460 <span class="indent">
1461 Options +Indexes<br />
1462 Order allow,deny<br />
1463 Allow from all<br />
1464 RewriteEngine on<br />
1465 RewriteCond %{REQUEST_FILENAME} !-f<br />
1466 RewriteCond %{REQUEST_FILENAME} !-d<br />
1467 RewriteRule ^(.*)$ /cgi-bin/blosxom.cgi/$1 [L,QSA]<br />
1469 </Directory><br />
1471 /home/sctemme/inst/blog/httpd/logs/rewrite_log<br />
1472 RewriteLogLevel 9<br />
1473 ErrorLog /home/sctemme/inst/blog/httpd/logs/error_log<br />
1474 LogLevel debug<br />
1475 CustomLog /home/sctemme/inst/blog/httpd/logs/access_log
1477 ScriptAlias /cgi-bin/ /home/sctemme/inst/blog/bin/<br />
1478 <Directory "/home/sctemme/inst/blog/bin"><br />
1479 <span class="indent">
1480 Options +ExecCGI<br />
1481 Order allow,deny<br />
1482 Allow from all<br />
1484 </Directory><br />
1486 </VirtualHost>
1490 The <code>RewriteCond
1492 and <code>RewriteRule
1494 directives say that, if the requested resource does not
1495 exist as a file or a directory, its path is passed to the
1496 Blosxom CGI for rendering. Blosxom uses Path Info to
1497 specify blog entries and index pages, so this means that if
1498 a particular path under Blosxom exists as a static file in
1499 the file system, the file is served instead. Any request
1500 that isn't pre- rendered is served by the CGI. This
1501 means that individual entries, which show the comments, are
1502 always served by the CGI which in turn means that your
1503 comment spam is always visible. This configuration also
1504 hides the Blosxom CGI from the user-visible URL in their
1505 Location bar. mod_rewrite is a fantastically powerful and
1506 versatile module: investigate it to arrive at a
1507 configuration that is best for your situation.
1513 <h3><a name="caching-content-with-mod_cache" id="caching-content-with-mod_cache">Caching Content With mod_cache
1516 <p>The mod_cache module provides intelligent caching of HTTP
1517 responses: it is aware of the expiration timing and content
1518 requirements that are part of the HTTP specification. The
1519 mod_cache module caches URL response content. If content sent
1520 to the client is considered cacheable, it is saved to disk.
1521 Subsequent requests for that URL will be served directly from
1522 the cache. The provider module for mod_cache, mod_disk_cache,
1523 determines how the cached content is stored on disk. Most
1524 server systems will have more disk available than memory, and
1525 it's good to note that some operating system kernels cache
1526 frequently accessed disk content transparently in memory, so
1527 replicating this in the server is not very useful.
1529 <p>To enable efficient content caching and avoid presenting the
1530 user with stale or invalid content, the application that
1531 generates the actual content has to send the correct response
1532 headers. Without headers like <code>Etag:
1534 ,<code>Last-Modified:
1538 ,mod_cache can not make the right decision on whether to cache
1539 the content, serve it from cache or leave it alone. When
1540 testing content caching, you may find that you need to modify
1541 your application or, if this is impossible, selectively disable
1542 caching for URLs that cause problems. The mod_cache modules are
1543 not compiled by default, but can be enabled by passing the
1544 option <code>--enable-cache[=shared]
1546 to the configure script. If you use a binary distribution of
1547 Apache httpd, or it came with your port or package collection,
1548 it may have mod_cache already included.
1552 <h4><a name="example-wiki" id="example-wiki">Example: wiki.apache.org
1556 <strong>'Is this still the case? Maybe we should give
1557 a better example here too.
1561 The Apache Software Foundation Wiki is served by MoinMoin.
1562 MoinMoin is written in Python and runs as a CGI. To date, any
1563 attempts to run it under mod_python has been unsuccessful.
1564 The CGI proved to place an untenably high load on the
1565 server machine, especially when the Wiki was being indexed
1566 by search engines like Google. To lighten the load on the
1567 server machine, the Apache Infrastructure team turned to
1568 mod_cache. It turned out <a href="/httpd/MoinMoin">MoinMoin
1570 needed a small patch to ensure proper behavior behind the
1571 caching server: certain requests can never be cached and
1572 the corresponding Python modules were patched to send the
1573 proper HTTP response headers. After this modification, the
1574 cache in front of the Wiki was enabled with the following
1575 configuration snippet in <code>httpd.conf
1580 <div class="example"><p><code>
1581 CacheRoot /raid1/cacheroot<br />
1582 CacheEnable disk /<br />
1583 # A page modified 100 minutes ago will expire in 10 minutes<br />
1584 CacheLastModifiedFactor .1<br />
1585 # Always check again after 6 hours<br />
1586 CacheMaxExpire 21600
1589 <p>This configuration will try to cache any and all content
1590 within its virtual host. It will never cache content for
1591 more than six hours (the <code>CacheMaxExpire
1593 directive). If no <code>Expires:
1595 header is present in the response, mod_cache will compute
1596 an expiration period from the <code>Last-Modified:
1598 header. The computation using <code>CacheLastModifiedFactor
1600 is based on the assumption that if a page was recently
1601 modified, it is likely to change again in the near future
1602 and will have to be re-cached.
1605 Do note that it can pay off to <em>disable
1609 header: For files smaller than 1k the server has to
1610 calculate the checksum (usually MD5) and then send out a <code>
1613 response, which will take waste some CPU and still saturate
1614 the same amount of network resources for the transfer (one
1615 TCP packet). For resources larger than 1k it might prove
1616 CPU expensive to calculate the header for each request.
1617 Unfortunately there does currently not exist a way to cache
1620 <div class="example"><p><code>
1621 <FilesMatch \.(jpe?g|png|gif|js|css|x?html|xml)><br />
1622 <span class="indent">
1629 This will disable the generation of the <code>ETag:
1631 header for most static resources. The server does not
1632 calculate these headers for dynamic resources.
1638 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
1639 <div class="section">
1640 <h2><a name="further-considerations" id="further-considerations">Further Considerations
1643 <p>Armed with the knowledge of how to tune a sytem to deliver the
1644 desired the performance, we will soon discover that <em>one
1646 system might prove a bottleneck. How to make a system fit for
1647 growth, or how to put a number of systems into tune will be
1648 discussed in <a href="/httpd/PerformanceScalingOut">
1649 PerformanceScalingOut
1654 <div class="bottomlang">
1655 <p><span>Available Languages: </span><a href="../en/misc/perf-scaling.html" title="English"> en </a></p>
1656 </div><div class="top"><a href="#page-header"><img src="../images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Comments</a></h2><div class="warning"><strong>This section is experimental!</strong><br />Comments placed here should not be expected
1657 to last beyond the testing phase of this system, nor do we in any way guarantee that we'll read them.</div>
1658 <div id="disqus_thread">
1659 </div><script type="text/javascript"><!--//--><![CDATA[//><!--
1661 var disqus_shortname = 'httpd';
1662 var disqus_identifier = window.location.href.replace(/(current|trunk)/, "2.4").replace(/\/[a-z]{2}\//, "/").replace(window.location.protocol, "http:") + '.' + lang;
1663 if (disqus_identifier.indexOf("httpd.apache.org") != -1) {
1665 var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
1666 dsq.src = window.location.protocol + '//' + disqus_shortname + '.disqus.com/embed.js';
1667 (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
1670 var text = document.createTextNode("Comments have been disabled for offline viewing.");
1671 document.getElementById('disqus_thread').appendChild(text);
1673 //--><!]]></script></div><div id="footer">
1674 <p class="apache">Copyright 2012 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
1675 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
1676 if (typeof(prettyPrint) !== undefined) {