Apache server – performance
Apache performance and analysis
Visualization of the situation
Load simulation on the server
Using the ApacheBench (AB) software
Using ApacheBench (AB) with Authentication
Using the Siege
Using the Siege with Authentication software
Advantage of using the Siege software
Using JMeter
Using Ngrinder
Performance Analysis
Visualization of Apache processes
Visualization of the pages processed by the process
CPU load problem analysis
Using modcache
Increased load due to an Input / Output (tmpfs) problem
Configuring Apache Execution (Worker vs. Prefork)
MPM prefork
MPM prefork Optimization
MPM worker
MPM Worker Optimization
Improved php performance
Use in cgi mode (php5-fpm)
Installation & configuration of php5-fpm
performance test with php5-fpm
Comparative with prefork and modphp5
Correction of data transfer
Global consideration to improve performance
Protection of your website
Reference:
Apache performance and analysis
It is very difficult to do a performance section because the problems can be very varied. A configuration can have an impact of improving meaning for an environment and in another environment having a negative impact. Moreover, depending on the point of view, the perception may be different, for example:
the sysadmin says: “The problem is the code, the developer has badly coded his thing: P”
The developer says: “It works very well on my computer, the problem is at the server level”
The project manager: “System access is more than planned”
Where is the truth in all this? I’ll tell you that the reality is a mix in all that, there is probably a possible code improvement because the server is different from the developer’s workstation. The sysadmin must be able to adjust this configuration for the applications that is installed on the machine. Let’s not forget the project manager: P, you have to be able to perform performance tests on the front system in order to know the number of clients that can be supported.
What are the classic problems that we find:
DNS problem
The load on the machine is too high (CPU usage)
Memory usage is high
The pages take a lot of time to answer, it’s so general that it does not give much information
Access to resources on the hard drive is slow
Depending on the time of day, the site responds with difficulty
The use of bandwidth is saturated
Visualization of the situation
Before starting to put efforts to correct the problem (s) try to identify them. Obviously we will see some applications that do not touch apache, but are purely system. Ideally you have a monitoring system and history of use that allows you to identify the period of the problem. When I mention monitoring de fact refers to a nagios type system that can receive email or SMS when problem. If your monitoring system does not allow you to keep graphs of values in the past, I advise you to put one in place to be able to identify after a period in problem. You have cacti which allows to carry out this operation. We will probably come back to this, and I will all provide a list of tools that will allow us to do the analysis of the moment without these tools.
Let’s start with a CPU usage problem.
Load simulation on the server
As performance training we finish with the load simulation however if I want to present the tools with the configuration that I currently only with my laptop without a real client this may be a little complicated. So we will see the load simulation right away. This can also be useful at the beginning of the project if you want to validate your application before going into production.
We will see several tools some more complex than others, unfortunately this will be a flyover because to make a good performance test it is necessary that they are related to your application. This will give you a starting point to complete your configuration. We will start with simple applications and we will ramp up at this point we will only analyze the logs to see the accesses later we will look at the performance analysis tools for apache.
The use of the utilities presented later will have to be executed on another machine than the server. This is to validate the entire network infrastructure as well. Local and remote behavior may vary, so your customers will be remote so simulated the same behavior. If you perform performance tests I also invite you to use multiple machines to support the server with multiple connection sources.
Using the ApacheBench (AB) software
ApacheBench (ab) is a command-line program for performance measurement and HTTP server load testing. Originally designed for Apache HTTP Server, it is now usable on all standard HTTP servers. The application is available of course under GNU / Linux and Windows (probably Mac).
Install the application:
$ sudo apt-get install apache2-utils
Let’s start with a small simple query we will realize a total of 100 queries so 10 simultaneous on the main pages of the site. With the -w option you can have the result in HTML format it can be practical:
$ ab -n 100 -c 10 -l https://www.linux202-siteA.com/
[ ... OUTPUT COUPÉ ... ]
Benchmarking www.linux202-siteA.com (be patient).....done
Server Software: Apache/2.4.7
Server Hostname: www.linux202-siteA.com
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
Document Path: /
Document Length: Variable
Concurrency Level: 10
Time taken for tests: 2.263 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 36900 bytes
HTML transferred: 10000 bytes
Requests per second: 44.19 [#/sec] (mean)
Time per request: 226.313 [ms] (mean)
Time per request: 22.631 [ms] (mean, across all concurrent requests)
Transfer rate: 15.92 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 33 189 77.2 201 456
Processing: 1 22 19.3 19 86
Waiting: 0 16 16.5 9 76
Total: 34 210 82.5 215 457
Percentage of the requests served within a certain time (ms)
50% 215
66% 237
75% 253
80% 258
90% 288
95% 363
98% 403
99% 457
100% 457 (longest request)
Explanation of the arguments:
-n: Total number of requests that will be forwarded
-c: Number of concurrent request passed
-l: The application will not report an error if the processing time of the request is not identical to the first realized. If your site is dynamic it is likely that the processing time will vary somewhat.
Explanation of the result:
Concurrency Level: 10
Time taken for tests: 2.263 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 36900 bytes
HTML transferred: 10000 bytes
Requests per second: 44.19 [#/sec] (mean)
Time per request: 226.313 [ms] (mean)
Time per request: 22.631 [ms] (mean, across all concurrent requests)
Transfer rate: 15.92 [Kbytes/sec] received
Concurrency Level: 10: Information on the number of concurrent connections
Time taken for tests: 2.263 seconds: The total time of the load test
Complete requests: 100: The total number of requests
Failed requests: 0: The number of requests in error
Total transferred: 36900 bytes: The amount of data transmitted during the test
HTML transferred: 10000 bytes: The amount of HTML data, excluding images and other media
Requests per second: 44.19 [# / sec] (mean): The number of requests per second
Time per request: 226.313 [ms] (mean): The time required for each request
- Time per request: 22.631 [ms] (mean, across all concurrent requests): The time per bulk request this returns to the value mentioned earlier divided by the number of concurrent request.
Transfer rate: 15.92 [Kbytes / sec] received: The transfer rate
The second part :
min mean[+/-sd] median max
Connect: 33 189 77.2 201 456
Processing: 1 22 19.3 19 86
Waiting: 0 16 16.5 9 76
Total: 34 210 82.5 215 457
Connect: The time taken to establish a connection to the server
Processing: The time taken to transmit the first bytes to the server and receive the first bytes of responses
Waiting: The time between sending the first bytes of data and the last bytes
Using ApacheBench (AB) with Authentication
We have seen previously the possibility of setting up an authentication system on sections of the site, we did it for an administrator section or when setting up the WebDAV solution. It is therefore likely that you want to validate these sections too. If you have implemented an apache authentication (htaccess) you can use the -A option:
$ ab -n 100 -c 10 -l -A admin:mot_passe https://www.linux202-siteA.com/admin/
However, if you have implemented authentication in your application this will not work, you probably used a session / cookie method. If this is the case you must use another option:
$ ab -n 100 -c 10 -l -C '_x3access_session=BAh7CUkiD3Nlc...' https://www.linux202-siteA.com/
REF : http://work.stevegrossi.com/2015/02/07/load-testing-rails-apps-with-apache-bench-siege-and-jmeter/
Using the Siege
ApacheBench (ab) is fine but let’s see another product that offers other possibilities, the combination of the 2 will allow us to better validate the capabilities of our servers. Let’s take a look at the same test that was done with ApacheBench to make our hand with something we know, and then we explore the advantage of Siege.
This time the name of the pasting is clearer:
$ sudo apt-get install siege
The arguments are a bit different from ab so we will redo the 100 queries so 10 concurrent. Here is the “formula” with seat.
$ siege -r 10 -c 10 https://www.linux202-siteA.com/
** SIEGE 3.0.5
** Preparing 10 concurrent users for battle.
The server is now under siege.. done.
Transactions: 100 hits
Availability: 100.00 %
Elapsed time: 6.75 secs
Data transferred: 0.01 MB
Response time: 0.06 secs
Transaction rate: 14.81 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 0.89
Successful transactions: 100
Failed transactions: 0
Longest transaction: 0.19
Shortest transaction: 0.03
Explanation of the arguments:
-r: The number of requests here 10
-c: The competing queries here 10
Result we will have 10 query (-r) * 10 concurrent queries (-c) = 100 Total queries
The seat result is less detailed than ApacheBench, although this may be sufficient depending on the need. I think the information provided is clear if this is not the case inform me I will try to update the document.
Using the Siege with Authentication software
All as ApacheBench siege is able to handle apache authentication or use cookie code sessions.
For Apache type authentication you must edit / create the .siegerc file in your home directory, with the following line:
login = admin:mot_de_passe
For the use of session cookie you will define a header with the information:
$ siege -r 10 -c 10 -H 'Cookie:_x3access_session=BAh7CUkiD3Nlc...' https://www.linux202-siteA.com/
Advantage of using the Siege software
At this stage seat and ApacheBench performs the same operation see what stands out. During the 2 previous tests we carried out a test of load only on ONE URL, seat allows us to define a file containing several URLs this allowing us to validate not only the main page but a series of page of the web site, because let’s be realistic your users will not settle for a page.
The -f option allows us to define a list of URLs siege will use its latest randomly to perform queries to the website. Demonstration:
$ cat sitea_urls.txt
https://www.linux202-sitea.com/
https://www.linux202-sitea.com/info.php
https://www.linux202-sitea.com/articles/2016/super_validation
https://www.linux202-sitea.com/app.php
$ sudo siege -r 10 -c 10 -f sitea_urls.txt
** SIEGE 3.0.5
** Preparing 10 concurrent users for battle.
The server is now under siege.. done.
Transactions: 100 hits
Availability: 100.00 %
Elapsed time: 8.20 secs
Data transferred: 0.52 MB
Response time: 0.10 secs
Transaction rate: 12.20 trans/sec
Throughput: 0.06 MB/sec
Concurrency: 1.22
Successful transactions: 100
Failed transactions: 0
Longest transaction: 0.40
Shortest transaction: 0.03
If you look at the log file of the website we clearly see the random side of the requests
$ tail -f /data/vhosts/siteA/logs/ssl_access.log
[ ... OUTPUT COUPÉ ... ]
172.17.0.2 - - [17/Jun/2016:08:12:01 -0400] "GET / HTTP/1.1" 200 2146 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:01 -0400] "GET /articles/2016/super_validation HTTP/1.1" 200 2798 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:01 -0400] "GET / HTTP/1.1" 200 2146 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:01 -0400] "GET /info.php HTTP/1.1" 200 19541 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:01 -0400] "GET /info.php HTTP/1.1" 200 19545 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:01 -0400] "GET /info.php HTTP/1.1" 200 19539 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:02 -0400] "GET /app.php HTTP/1.1" 200 1923 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:02 -0400] "GET / HTTP/1.1" 200 2146 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
172.17.0.2 - - [17/Jun/2016:08:12:02 -0400] "GET /info.php HTTP/1.1" 200 19538 "-" "Mozilla/5.0 (pc-i686-linux-gnu) Siege/3.0.5"
All using the ability to use a random URL sequence we will define a competing user number for a period of time. We will also define a delay between each request of the users by default the time between each request is 1 seconds, however to simulate the time of “reading” or awareness of the content we will define 5 seconds between the requests.
So 25 concurrent users, for 5 minutes, with 5 seconds delay between queries for a period of 5 minutes.
$ siege -c 25 -t 5M -d 5 -f sitea_urls.txt
** SIEGE 3.0.5
** Preparing 25 concurrent users for battle.
The server is now under siege...
Lifting the server siege... done.
Transactions: 2950 hits
Availability: 100.00 %
Elapsed time: 299.19 secs
Data transferred: 13.05 MB
Response time: 0.04 secs
Transaction rate: 9.86 trans/sec
Throughput: 0.04 MB/sec
Concurrency: 0.44
Successful transactions: 2950
Failed transactions: 0
Longest transaction: 0.36
Shortest transaction: 0.03
We are left with a more representative test of the use in the nature of our website, the problem with this solution is your test is not reproducible. Indeed as the choice of URLs is made randomly 2 tests even consecutive will not achieve the same access, we can say that this is good because it is likely that your users always access in the same sequence your pages but the result of numbers are more complicated to interpret.
Using JMeter
REF :
http://jmeter.apache.org/
Using Ngrinder
REF :
https://hub.docker.com/r/ngrinder/controller/
https://github.com/naver/ngrinder/wiki/
Performance Analysis
Now that we are able to simulate traffic on our server we will be able to visualize the behavior of the server. We will see the behavior of apache when mounted on load, this part of visualization is as important as the configuration section. Each server / website combination being unique you must be able to identify the problematic point to be able to improve it. There is no recipe that applies regardless of the sauce.
Visualization of Apache processes
Let’s start with the Apache process visualization, the web server can work in 2 mode:
prefork: This multi-process module (MPM) implements a web server with early process start. Each server process can respond to incoming requests, and a parent process controls the size of the child process set. So we have the Apache process that usually starts under the root user so that we can listen on port 80 and / or 443, later the other processes are forked under the Apache user. What for? Each new process is started according to the fork principle. The fork function is part of the standard UNIX system calls (POSIX standard). This function allows a process (a running program) to give birth to a new process that is its true copy, for example in order to perform a second process parallel to the first one. A good way to visualize the effect of a fork on a process is to imagine a bacterium that cuts in two. In other words, a complete copy of the process with a new PID is generated on the system, the set of memory allocations realized from the parent process are transmitted to the child process. Apache always tries to keep several server processes inactive or in reserve, so that incoming requests can be processed. This way, customers do not have to wait for a new child process to start before their requests can be processed. The MaxConnectionsPerChild directive controls how often the server recycles its processes by stopping older ones and launching new ones.
worker: This multi-process module (MPM) implements a multi-threaded multi-threaded hybrid server. By using threads to serve queries, it can handle many queries while consuming fewer resources than a process-based server. However, it retains much of the stability of a process-based server by maintaining multiple processes available, each of which has many threads. A single control process (the parent) is responsible for starting child processes. Each child process creates a fixed number of server threads based on the value of the ThreadsPerChild directive, as well as a thread that waits for connections and passes them to a server thread for processing as they arrive. The Apache HTTP server always tries to maintain a set of idle or inactive server threads, which are ready to process incoming requests. In this way, customers do not have to wait for a new thread or process to be created before their requests can be processed. The big advantage of this module is that unlike the fork system it is not a complete copy of the parent process that is duplicated but only a start process, it also uses less memory because the threads share a memory space to exchange the information on the server. However, not all apache modules work in the most well-known threaded mode php (2016) in worker mode.
Here is a graphical representation of the two modes:

I’m going to focus on the mpm_prefork system, I’ll let you have fun if your system uses worker to correlate with the other mode.
Let’s see the current configuration of the mpm_prefork mode:
$ cat /etc/apache2/mods-enabled/mpm_prefork.conf
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxRequestWorkers: maximum number of server processes allowed to start
# MaxConnectionsPerChild: maximum number of requests a server process serves
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
When we start the httpd service we will have 5 available Apache processes (StartServers).
If I access the website 1 of the above process will take the task and provide the requested information to the customer. If we support the system will create other process to meet the demand. Demonstration, you can use the top command to view live process augmentation …$ sudo /etc/init.d/apache2 start
* Starting web server apache2
*
$ ps aux | grep apache
root 51 0.6 0.9 90420 19460 ? Ss 17:04 0:00 /usr/sbin/apache2 -k start
www-data 56 0.0 0.2 90452 5376 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 57 0.0 0.2 90452 5380 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 58 0.0 0.2 90452 5380 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 59 0.0 0.2 90452 5380 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 60 0.0 0.2 90452 5380 ? S 17:04 0:00 /usr/sbin/apache2 -k start
[client ]$ ab -n 100 -c 10 -l https://www.linux202-siteA.com/
[server ]$ ps aux | grep apache
root 51 0.0 0.9 90420 19460 ? Ss 17:04 0:00 /usr/sbin/apache2 -k start
www-data 56 0.1 0.4 90512 8432 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 57 0.1 0.4 90512 8432 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 58 0.1 0.4 90512 8432 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 59 0.1 0.4 90512 8432 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 60 0.1 0.4 90512 8432 ? S 17:04 0:00 /usr/sbin/apache2 -k start
www-data 70 5.2 0.4 90512 8432 ? S 17:10 0:00 /usr/sbin/apache2 -k start
www-data 71 2.1 0.4 90512 8432 ? S 17:10 0:00 /usr/sbin/apache2 -k start
www-data 72 1.7 0.4 90512 8432 ? S 17:10 0:00 /usr/sbin/apache2 -k start
So we see that now with 9 apache process. Let’s be a little more brutal now:
We see the number of Apache processes skyrocketing, once the mounted load is completed the number of processes will reduce by itself. This number corresponds to the MaxSpareServers directive:[client]$ ab -n 200 -c 20 -l https://www.linux202-siteA.com/
[server]$ ps aux | grep apache
root 51 0.0 0.9 90420 19460 ? Ss 17:04 0:00 /usr/sbin/apache2 -k start
www-data 56 0.2 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 57 0.2 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 58 0.2 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 59 0.2 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 60 0.2 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 70 0.6 0.4 90512 8436 ? S 17:10 0:01 /usr/sbin/apache2 -k start
www-data 71 0.6 0.4 90512 8436 ? S 17:10 0:00 /usr/sbin/apache2 -k start
www-data 72 0.5 0.4 90512 8436 ? S 17:10 0:00 /usr/sbin/apache2 -k start
www-data 130 2.5 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 136 1.9 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 161 6.6 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 164 4.5 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 165 3.5 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 168 2.3 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 169 3.3 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 170 2.3 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 171 5.0 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 174 1.0 0.3 90488 7380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 175 1.0 0.3 90488 7380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 178 1.0 0.3 90488 7380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 179 0.0 0.2 90452 5380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 180 0.0 0.2 90452 5380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 181 0.0 0.2 90452 5380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
[server] $ ps aux | grep apache
root 51 0.0 0.9 90420 19460 ? Ss 17:04 0:00 /usr/sbin/apache2 -k start
www-data 56 0.1 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 57 0.1 0.4 90512 8436 ? S 17:04 0:01 /usr/sbin/apache2 -k start
www-data 70 0.3 0.4 90512 8436 ? S 17:10 0:01 /usr/sbin/apache2 -k start
www-data 72 0.2 0.4 90512 8436 ? S 17:10 0:00 /usr/sbin/apache2 -k start
www-data 130 0.3 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 161 0.1 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 164 0.1 0.4 90512 8432 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 174 0.0 0.3 90488 7380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 175 0.0 0.3 90488 7380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
www-data 181 0.0 0.2 90452 5380 ? S 17:12 0:00 /usr/sbin/apache2 -k start
In theory the number of processes that apache could start corresponds to the directive MaxRequestWorkers, however in my case my laptop will not be able to answer the load before: P. Why limited the number of processes will you tell me? If you are slashed for example so a significant increase in access to your website, if the number of processes was unlimited, in case your website is able to provide 1000 users when the 1001 arrives your server would only be more able to answer TOTALLY to NO user. If you have properly configure your server apache the 1001 user will not be able to access the page however the other 1000 will not see anything.
Visualization of the pages processed by the process
Good to see apache process is fine, it allows us to visualize the use of the server but if we see an apache process that takes 100% of the CPU or a huge number of processes how can I know the source and or the destination queries?!?! Some will tell me to consult the logs, it is a VERY good idea unfortunately if you have mutualize 200 sites on your server it will be completely unreadable: – /. You can use google systems analytics or piwik cons you may have some problem to correlate with the PID process on your machine 🙁 Well you can imagine that if I take as much time to tell you all this is that I have a solution: P.
There is a module that provides real-time access information on the server is mod_status, the module is activated by default on Ubuntu but only accessible locally on the server. We will therefore make a small configuration to allow access from our machine.
$ sudo vim /etc/apache2/mods-enabled/status.conf
[... OUTPUT COUPÉ ...]
SetHandler server-status
#Require local
Require ip 172.17.42.1
[... OUTPUT COUPÉ ...]
In the situation I only allowed the IP 172.17.42.1, must reload the apache configuration for it to be active.
Here is the cold result:

We can already see that the request on this page was processed by PID 383. Indeed if I list the processes running on the machine:
$ ps aux | grep apache
root 380 0.0 0.9 90420 19552 ? Ss 17:42 0:00 /usr/sbin/apache2 -k start
www-data 383 0.0 0.4 90684 8836 ? S 17:42 0:00 /usr/sbin/apache2 -k start
www-data 384 0.0 0.2 90452 5424 ? S 17:42 0:00 /usr/sbin/apache2 -k start
We will now see the behavior when accessing multiple pages using the seat:
$ cat sitea_urls.txt
https://www.linux202-sitea.com/
https://www.linux202-sitea.com/info.php
https://www.linux202-sitea.com/articles/2016/super_validation
https://www.linux202-sitea.com/app.php
$ siege -r 20 -c 20 -f sitea_urls.txt

So the big advantage is to be able to have the details of what a process does, you have the pid and the VirtualHost that is requested as well as the requested page. All with the IP address of origin, if you are a victim of a DOS you are able to know where and especially to which page.
We can see the status of web page requests using the login system:
Scoreboard Key:
"_" Waiting for Connection
"S" Starting up
"R" Reading Request,
"W" Sending Reply
"K" Keepalive (read)
"D" DNS Lookup,
"C" Closing connection
"L" Logging
"G" Gracefully finishing
"I" Idle cleanup of worker
"." Open slot with no current process
Anecdote: In the past, a customer had a problem of availability of web page, a dynamic page that was more than solicited. The problem was that the web server could no longer process the requests, thanks to the visualization of the requested page we could put a static web page html, so less cumbersome to mention a problem of availability of the service.
CPU load problem analysis
To perform the analysis we will install the sysstat passthrough if this is not already present.
$ apt-cache search iostat
sysstat - system performance tools for Linux
$ sudo apt-get install sysstat
To continue we will put a php page not performing, and I did it: D … I wanted a page that takes a lot of CPU. So I create a page that displays 100 times a random number of 10000 characters. We will go back for the beauty of the operation, but the result is the rendezvous the CPU increases: D.
$ sudo vim /data/vhosts/siteA/docroot/perf/random.php
If you go on the URL: https://www.linux202-sitea.com/perf/random.php, you will have a list of character, if you click to refresh the page other number will be present.
We will now support the server, we will visualize the behavior with the vmstat command:
[client]$ ab -n 200 -c 10 -l https://www.linux202-siteA.com/perf/random.php
Concurrency Level: 10
Time taken for tests: 20.719 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 100047400 bytes
HTML transferred: 100000000 bytes
Requests per second: 9.65 [#/sec] (mean)
Time per request: 1035.974 [ms] (mean)
Time per request: 103.597 [ms] (mean, across all concurrent requests)
Transfer rate: 4715.49 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 64 143 36.9 139 293
Processing: 400 883 129.8 897 1265
Waiting: 141 545 96.4 551 889
Total: 540 1026 141.6 1038 1430
Percentage of the requests served within a certain time (ms)
50% 1038
66% 1088
75% 1116
80% 1141
90% 1183
95% 1224
98% 1334
99% 1398
100% 1430 (longest request)
$ vmstat 5 20
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
13 0 940 951656 74600 503100 0 0 266 37 322 525 26 3 70 1 0
11 0 940 947320 74600 503140 0 0 0 0 1228 3242 94 6 0 0 0
10 0 940 946772 74624 503164 0 0 0 13 1271 3252 94 6 0 0 0
11 0 940 955588 74648 503192 0 0 0 12 1172 3224 94 6 0 0 0
5 0 940 955292 74672 503208 0 0 0 11 1286 3170 94 6 0 0 0
0 0 940 959788 74696 503236 0 0 0 14 812 1145 8 3 89 0 0
1 0 940 961992 74720 503248 0 0 0 13 727 899 3 1 96 0 0
Of course you can also use the command top to visualize the behavior, I wanted to introduce you another possible method that is well script and provides all the information of the system (Memory, Input / Ouput, cpu …). If you want to use top in script it is also possible with the -b option for batch which is very practical.
# Avant test de charge
$ uptime
17:11:59 up 22 min, 1 user, load average: 0.96, 1.62, 1.42
# Après test de charge
$ uptime
17:13:02 up 23 min, 1 user, load average: 2.81, 1.96, 1.55
In the following situation, what is the solution?
Correct the php code, it would be the solution to put in place because clearly there is a problem, however this is not always possible at our level
So what is the workaround that can be put in place?
Of course this depends on your application, in this case the question that I can ask myself: is the random number must change each refresh? Can I set up a cache system so that it is generated only at a defined interval?
We could modify the php code so that it adds a header (header) html so that the client hides the content of the page. This is a very good solution unfortunately as the cache system will be done at the client if I have a lot of query from multiple source, caching operation of the page will NOT be done. At least not as we hear, the load on the server will be the same, it will solve the problem if the same client / browser accesses the page.
So we will introduce the cache system at the server level, the result will be:
The server will generate the result of the php dynamic page once
Subsequently the apache server will hide the content in this memory
In future requests, the same content will be sent to the applicant
Once the cache expires the page will be regenerated and hidden, so on.
Of course the negative side of this operation is that the dynamic content will not be generated at each request, but if we think a little if we take a news site such as lemonde.fr, lapresse.ca, … If we use a 5-minute cache system to answer thousands of requests, is it really critical?!?!
Using mod_cache
The module that we will use for our needs will be mod_cache, we will see only a flyover, however this will offer you the possibility to go further by yourself.
The system mod_cache function with 2 mode:
mod_cache_disk implements a disk storage manager. The headers and bodies are stored separately on the disk in a directory structure based on the md5 digest of the cached URL. Multiple Negotiated Content Responses can be stored at the same time, but partial content caching is not supported by this module. The htcacheclean utility allows you to list and delete cached URLs, and to keep the cache below certain size and number of inode limits.
mod_cache_socache Implements a storage manager based on a shared object cache. Headers and bodies are stored together under a single key based on the URL of the cached response. Negotiated multiple-content responses can be stored simultaneously, but this module does not support caching of partial content.
We will start with the first is very equivalent with the second so no stress: D. Warning the name of the module for hidden in memory is not the same with the version apache 2.2.
We will activate the modules that is already available under Ubuntu.
$ ls /etc/apache2/mods-available/*cache*
/etc/apache2/mods-available/authn_socache.load /etc/apache2/mods-available/file_cache.load
/etc/apache2/mods-available/cache.load /etc/apache2/mods-available/socache_dbm.load
/etc/apache2/mods-available/cache_disk.conf /etc/apache2/mods-available/socache_memcache.load
/etc/apache2/mods-available/cache_disk.load /etc/apache2/mods-available/socache_shmcb.load
/etc/apache2/mods-available/cache_socache.load
$ sudo a2enmod cache
Enabling module cache.
To activate the new configuration, you need to run:
service apache2 restart
$ sudo a2enmod cache_disk
Considering dependency cache for cache_disk:
Module cache already enabled
Enabling module cache_disk.
To activate the new configuration, you need to run:
service apache2 restart
$ ls /etc/apache2/mods-enabled/*cache*
cache.load cache_disk.conf cache_disk.load socache_shmcb.load
Let’s look at the cache configuration file for the hard drive that is set by default without the comments:
$ cat /etc/apache2/mods-enabled/cache_disk.conf | grep -v "#" | grep -v "^$"
CacheRoot /var/cache/apache2/mod_cache_disk
CacheDirLevels 2
CacheDirLength 1
We have the configuration of the directory that will be used to store cached content this via the CacheRoot directive. The CacheDirLevels directive sets the number of subdirectory levels that the cache will contain. The CacheDirLength directive sets the number of characters that each subdirectory name in the cache hierarchy will contain.
We have the configuration of the directory that will be used to store cached content this via the CacheRoot directive. The CacheDirLevels directive sets the number of subdirectory levels that the cache will contain. The CacheDirLength directive sets the number of characters that each subdirectory name in the cache hierarchy will contain.
If we look at the directory defined by CacheRoot we will find that the permissions are set for the user running the web server:
$ ls -ld /var/cache/apache2/mod_cache_disk
drwxr-xr-x 2 www-data www-data 4096 Jan 14 12:46 /var/cache/apache2/mod_cache_disk
If you choose to change this configuration do not forget to adjust the configurations accordingly.
At this point even if I redo a load test I would have exactly the same behavior as before because although the modules are loaded and configure “globally” no virtual server has to activate it! So we will enable it for the siteA virtual server.
$ sudo vim /etc/apache2/sites-enabled/siteA-ssl.conf
[... OUTPUT COUPE ...]
Alias "/cm-images" "/data/vhosts/common/images"
# Mise en cache de tous les contenus
CacheEnable disk /
Options none
AllowOverride ALL
Require all granted
[... OUTPUT COUPE ...]
We validate the configuration and restart, I have to restart, because there are modules to load.
$ sudo apachectl configtest && sudo /etc/init.d/apache2 restart
Syntax OK
* Restarting web server apache2
...done.
We activated the cache and performed the restart of apache, go on the pages of the site.
https://www.linux202-sitea.com/perf/random.php
https://www.linux202-sitea.com/
With the htcacheclean command you can see the content that is cached:
$ sudo htcacheclean -A -p /var/cache/apache2/mod_cache_disk/
https://www.linux202-sitea.com:443/Free_Software_Foundation_logo.png? 620 37866 200 0 1466682926812864 1466769326812864 1466682926812463 1466682926812864 1 0
https://www.linux202-sitea.com:443/index.html? 612 109 200 0 1466682926780187 1466769326780187 1466682926779031 1466682926780187 1 0
$ sudo htcacheclean -a -p /var/cache/apache2/mod_cache_disk/
https://www.linux202-sitea.com:443/Free_Software_Foundation_logo.png?
https://www.linux202-sitea.com:443/index.html?
WARNING: Do not forget to use the command with sudo otherwise your user does not have the permission to access the content you will have a result EMPTY.
why do not we see the PHP page in the system the list of hidden pages?!?! We will have to put a small modification in the php page, we will have to define HTML header. Here is what we will add:
$ sudo vim /data/vhosts/siteA/docroot/perf/random.php
<?php
function generateRandomString($length = 100000) {
[... OUTPUT COUPÉ ...]
We have 2 header: TODO: to complete
Cache-Control: must-revalidate, max-age = 3600 *:
Vary: Accept-Encoding:
We validate: D, we return to the page and we reuse the command:
$ sudo htcacheclean -a -p /var/cache/apache2/mod_cache_disk/
https://www.linux202-sitea.com:443/perf/random.php
[... OUTPUT COUPÉ ...]
It’s time to repeat a performance test: D.
[client]$ ab -n 200 -c 10 -l https://www.linux202-siteA.com/perf/random.php
Concurrency Level: 10
Time taken for tests: 4.369 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 2134200 bytes
HTML transferred: 2080000 bytes
Requests per second: 45.78 [#/sec] (mean)
Time per request: 218.458 [ms] (mean)
Time per request: 21.846 [ms] (mean, across all concurrent requests)
Transfer rate: 477.02 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 34 190 86.2 209 328
Processing: 1 20 18.1 14 93
Waiting: 1 13 14.2 9 79
Total: 35 210 94.7 239 341
Percentage of the requests served within a certain time (ms)
50% 239
66% 283
75% 297
80% 302
90% 313
95% 320
98% 325
99% 330
100% 341 (longest request)
$ uptime
# avant
17:25:22 up 35 min, 1 user, load average: 0.70, 0.85, 1.06
$ vmstat 5 20
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 940 877884 75524 520964 0 0 174 28 365 604 25 3 71 1 0
10 0 940 875124 75524 520992 0 0 0 1 844 1999 64 4 31 0 0
0 0 940 876540 75548 521004 0 0 0 30 855 1650 33 4 64 0 0
# Apres
$ uptime
17:26:16 up 36 min, 1 user, load average: 1.06, 0.96, 1.09
We can say that it WALK: D, woot !! Well it’s not a reason to program like a pig ;-).
I told you this is just an introduction to the system we will all take the time to explore a little options available one is in must enjoy: D.
When we activate a cache system the first question we often ask is how long will the system hide the information?!?! This is defined by the CacheDefaultExpire directive

As you can see, the default value is 3600 seconds, but I would like to focus on where this directive can be defined, the context: server configuration, virtual server, directory, .htaccess.
As you can see this can be over-defined in several places as needed !!
The other issue that can be raised is, yeah but I do not want ALL of my website to be hidden, it’s just a section that I have a problem with …
Actually for the demonstration I activated the cache for the whole site but look at the CacheEnable directive.

Again I point you to the context line which indicates a non-negligible list where we can activate the caching mode.
Good for people who want to activate it for a directory but not a file, yes there are needs sometimes like this: P. The CacheDisable directive is for that again the list of places where this can be defined is consistent with the need …

According to the definition of the directive you can use it as follows:
<Location "/foo">
CacheDisable on
# Ou
CacheDisable "/path/url/fichier/toto.html"
I will not cover here the module for hidden in memory the concept being similar I will continue to cover more material in case you want me to add this section PLEASE say it: D.
Increased load due to an Input / Output (tmpfs) problem
Well we have corrected the problem of CPU load, as we have seen in the previous example the CPU load was mainly due to an increase in CPU user percentage. We generated a process that generated a random number (pocket: P) which resulted in increasing the load.
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
13 0 940 951656 74600 503100 0 0 266 37 322 525 26 3 70 1 0
11 0 940 947320 74600 503140 0 0 0 0 1228 3242 94 6 0 0 0
10 0 940 946772 74624 503164 0 0 0 13 1271 3252 94 6 0 0 0
As we can see above the increase is under the US column for the CPU section. Let’s see another case of increasing the load but this time due to a wait-access (WA) problem, usually caused by an intensive access to write or read the hard disk.
I’m going to create a 27 Megs text file named data.dtd:
$ pwd
/data/vhosts/siteA/docroot/perf
$ tail data.dtd
2016-06-13 08:42:31 status unpacked sysstat:i386 10.2.0-1
2016-06-13 08:42:31 status unpacked sysstat:i386 10.2.0-1
2016-06-13 08:42:31 status unpacked sysstat:i386 10.2.0-1
2016-06-13 08:42:31 status unpacked sysstat:i386 10.2.0-1
2016-06-13 08:42:31 status unpacked sysstat:i386 10.2.0-1
2016-06-13 08:42:31 status half-configured sysstat:i386 10.2.0-1
2016-06-13 08:42:32 status installed sysstat:i386 10.2.0-1
2016-06-13 08:42:32 trigproc libc-bin:i386 2.19-0ubuntu6
2016-06-13 08:42:32 status half-configured libc-bin:i386 2.19-0ubuntu6
2016-06-13 08:42:32 status installed libc-bin:i386 2.19-0ubuntu6
$ du -hs data.dtd
27M data.dtd
I will create a php file that will read and write this file under another name then delete it:
$ sudo vim /data/vhosts/siteA/docroot/perf/io-file.php
$ sudo mkdir /data/vhosts/siteA/docroot/perf/tmp
$ sudo chown www-data /data/vhosts/siteA/docroot/perf/tmp
As there is writing on the hard disk, I do not want my page is hidden otherwise the system will not perform the operation each time access to the site: – /. So the option of caching with mod_cache is not an option in this case so I disable the option.
$ head -30 /etc/apache2/sites-enabled/siteA-ssl.conf
ServerAdmin webmaster@localhost
ServerName www.linux202-siteA.com
ServerAlias linux202-siteA.com
ServerAlias toto.linux202-siteA.com
DocumentRoot /data/vhosts/siteA/docroot/
Alias "/cm-images" "/data/vhosts/common/images"
# Mise en cache de tous les contenus
#CacheEnable disk /
#CacheIgnoreCacheControl On
#CacheDefaultExpire 3600
[... OUTPUT COUPÉ ...]
We restart the apache service and we will do a test
$ sudo apachectl configtest && sudo /etc/init.d/apache2 restart
I will reuse the ab command to load the server and we will view the behavior with vmstat on the server.
[client]$ ab -n 200 -c 10 -l https://www.linux202-siteA.com/perf/io-file.php
Document Path: /perf/io-file.php
Document Length: Variable
Concurrency Level: 10
Time taken for tests: 66.105 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 80040200 bytes
HTML transferred: 80002000 bytes
Requests per second: 3.03 [#/sec] (mean)
Time per request: 3305.268 [ms] (mean)
Time per request: 330.527 [ms] (mean, across all concurrent requests)
Transfer rate: 1182.42 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 34 130 64.4 128 338
Processing: 260 3153 1847.1 2666 8556
Waiting: 205 2879 1841.3 2405 8336
Total: 295 3283 1841.0 2767 8675
Percentage of the requests served within a certain time (ms)
50% 2767
66% 3643
75% 4174
80% 4630
90% 5822
95% 7789
98% 8035
99% 8477
100% 8675 (longest request)
[server]$ vmstat 2 30
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 3280 369692 72788 1029732 0 1 186 1194 337 594 10 5 82 3 0
10 0 3280 238252 72796 1050980 0 0 50 60 533 765 18 12 70 0 0
7 0 3280 224696 72800 1056976 0 0 22 26014 5236 11333 35 62 4 0 0
0 12 3784 52768 72800 1071464 16 252 62 47898 4806 10102 33 61 0 6 0
3 13 4652 52848 72816 1065776 12 434 60 36304 6132 13241 11 27 0 62 0
2 9 4888 55556 72148 1062744 0 118 20 34436 1815 3370 22 22 0 56 0
0 10 5088 53288 69948 1068768 8 100 16 17190 4251 8884 9 14 0 77 0
2 12 5092 108800 69980 1051752 0 2 20 45946 1419 3885 7 18 1 73 0
9 1 9412 95056 70020 1059816 0 2160 0 20222 1549 5115 8 13 4 75 0
0 3 9412 72108 70044 1056564 0 0 4 36604 1299 5678 28 32 0 40 0
6 0 9512 50720 70060 1078776 0 50 0 41082 4313 10174 6 32 2 60 0
11 0 9792 69936 70060 1058804 0 140 0 63094 4520 10074 38 60 1 1 0
0 4 9792 58196 70072 1064724 0 0 0 59588 5369 12786 33 54 1 13 0
11 0 9792 154456 70088 1055740 0 0 4 29520 2257 8491 12 19 0 68 0
10 1 10324 147376 67184 1047248 0 266 8 68910 4080 8758 37 57 2 4 0
0 6 10324 77544 67192 1054612 0 0 6 15918 4640 10404 27 46 0 27 0
8 2 11644 54444 62904 1084604 0 660 10 41374 955 7323 10 25 14 52 0
0 5 11968 68560 62232 1067420 0 162 4 20014 3465 8940 30 37 0 33 0
0 2 12224 95116 62244 1047644 0 128 8 67342 2957 6338 34 57 1 8 0
2 5 13148 51240 62248 1091084 0 462 2 59418 2167 5202 16 27 1 56 0
0 3 13256 51636 62256 1090584 0 54 0 11078 484 442 2 1 0 97 0
6 0 13616 157088 58512 1040012 0 180 12 37504 4452 9477 30 43 0 27 0
0 7 13620 48864 58148 1100000 0 2 14 59066 3285 7892 26 55 0 19 0
7 9 14476 160316 57192 1059464 0 428 98 52044 4935 30204 24 33 0 43 0
0 10 14476 58264 57192 1088112 0 0 18 3938 2510 4311 5 18 0 77 0
0 7 19244 67108 49160 1087016 0 2384 4 60674 3020 8848 26 45 0 29 0
0 4 19244 62888 49164 1097100 0 0 0 18604 800 1125 3 2 0 95 0
8 3 19244 120060 49208 1074256 0 0 140 31384 1019 5032 26 29 0 44 0
1 6 19244 64604 49224 1107128 0 0 0 71612 2090 12644 36 57 1 6 0
2 3 20540 53464 39044 1121280 0 648 0 21408 5930 12650 3 14 0 83 0
$ uptime
17:22:34 up 27 min, 1 user, load average: 9.56, 3.39, 1.67
The question is how can I fix this problem, caching is not an option because you have to write every call. I can not provide a pre-generated page to the client, again it is probably possible to correct the problem at the code level (yeahhh I’m a sysadmin, so the problem is the code: P). Well, what workaround is available to me?!?! In this case it could also be network access on a shared drive or other … Let’s be imaginative: D.
The first idea that you think you need a SSD is a very good idea what is the required size?!?! And you have how many server that must have SSD present? Imagine that these files are “temporary” processing files so you would need 2 or 3 Gig on each server, with a cluster of 30 machines. The price of SSDs for servers are very expensive and unfortunately the SSD is not optimal for writing the longevity of HDs are greatly impacted.
The second idea why it is not written in the memory … The php script will keep the information in memory and do all the treatment … Super idea but is the following process done by the page? php ?? Is it a process that does the treatment and how long does it take? Is it really possible to keep the user the time of the 2 treatments?!? Probably not .
Here is my proposal, put in place a fake directory that will actually be in the system memory, result writing time is SUPER performance because performed in memory. The file will be available on the file system as a normal file and can be processed by another application when the time comes. The bad point: If the server crashes the data is lost, yep nothing is perfect: P.
Let’s see the result, set up the solution:
$ sudo vim /etc/fstab
[... OUTPUT COUPÉ ...]
tmpfs /data/vhosts/siteA/docroot/perf/tmp tmpfs nodev,nosuid,size=1G 0 0
I configure the tmpfs service so that it is set for the / data / vhosts / siteA / docroot / perf / tmp directory I give it 1 gig of maximum memory. Let’s put it up.
$ sudo mount /data/vhosts/siteA/docroot/perf/tmp
$ sudo mount | grep perf
tmpfs on /data/vhosts/siteA/docroot/perf/tmp type tmpfs (rw,nosuid,nodev,relatime,size=1048576k)
We redo a test ??
[client] $ ab -n 200 -c 10 -l https://www.linux202-siteA.com/perf/io-file.php
Document Path: /perf/io-file.php
Document Length: Variable
Concurrency Level: 10
Time taken for tests: 28.298 seconds
Complete requests: 200
Failed requests: 0
Total transferred: 80040200 bytes
HTML transferred: 80002000 bytes
Requests per second: 7.07 [#/sec] (mean)
Time per request: 1414.915 [ms] (mean)
Time per request: 141.492 [ms] (mean, across all concurrent requests)
Transfer rate: 2762.15 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 38 145 41.2 140 255
Processing: 584 1258 196.2 1267 1685
Waiting: 399 946 166.2 955 1299
Total: 693 1402 211.1 1403 1885
Percentage of the requests served within a certain time (ms)
50% 1403
66% 1491
75% 1557
80% 1592
90% 1660
95% 1741
98% 1834
99% 1840
100% 1885 (longest request)
[server] $ $ vmstat 2 40
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 21452 331592 35516 1115720 0 4 117 1266 329 583 13 4 79 3 0
10 0 21532 100284 32940 1121244 0 40 12 40 3836 7251 27 49 24 0 0
10 0 21768 216136 32940 1086536 0 118 0 118 2377 3998 47 54 0 0 0
10 0 21768 90072 32948 1111180 0 0 0 6 1966 4121 43 57 0 0 0
9 0 21768 67004 32972 1128720 0 0 0 30 3253 6686 45 55 0 0 0
13 0 22488 173208 32972 1080800 0 360 0 360 3488 6753 47 53 0 0 0
11 0 22488 237528 32996 1090832 0 0 0 30 4113 8468 49 50 1 0 0
7 0 22488 96588 32996 1094072 0 0 0 8 1474 3155 43 57 0 0 0
10 0 22664 155992 32448 1074988 0 88 0 88 1934 4156 47 53 0 0 0
6 0 22664 183056 32472 1059836 0 0 0 28 1299 2791 47 53 0 0 0
9 0 22664 130136 32472 1076684 0 0 0 0 4219 8722 41 59 0 0 0
9 0 22664 222444 32496 1063548 0 0 0 30 2267 4985 50 50 0 0 0
8 0 22664 111852 32496 1081300 0 0 0 0 3195 6426 41 59 0 0 0
10 0 22664 160976 32496 1061252 0 0 0 0 3926 8204 44 56 0 0 0
10 0 22664 225652 32520 1088308 0 0 0 28 3439 7062 49 51 0 0 0
$ uptime
17:39:35 up 44 min, 1 user, load average: 2.86, 1.25, 1.10
We can clearly see that disk access has remained at 0 all along the process, the load on the CPU is mounted but only because of user processes, but much less. The result of the load test is much better.
But I repeat, if you use this technique you have to make a copy or a processing of the files that are TEMPORARY. If there is a crash there is data loss, of course you could put all your website in memory this will increase the performance of the server: D.
Configuring Apache Execution (Worker vs. Prefork)
At the apache process presentation I made mention of 2 modes available with the prefork system and with the Thread system. This was a simple presentation to inform of the situation we will now see in more detail the 2 modes, we started with the default configuration for the presentation, we will handle it now.
MPM prefork
As mentioned in the previous presentation the prefork system, fork a new apache process to handle new queries. During the Fork a copy of the parent process is made with its memory stack, this is the original system set up with apache, so all the modules work with this mode, which is not true with the other system.
A single monitoring process is tasked with initiating child processes that wait for connections and process them as they arrive. Apache httpd always tries to keep several server processes inactive or in reserve, so that incoming requests can be processed. This way, customers do not have to wait for a new child process to start before their requests can be processed.
The parent process is usually started as root on Unix so that you can listen on port 80, the child processes are started by Apache httpd under a restricted user. The privileges granted to Apache httpd child processes can be controlled using the User and Group directives. The child processes must be able to read all the content to be served, but their privileges must be as low as possible.
The StartServers, MinSpareServers, MaxSpareServers, and MaxRequestWorkers directives control how the parent process creates child processes to process queries. Sites that need to process more than 256 simultaneous requests must increase the value of MaxRequestWorkers, while sites with a limited memory resource must decrease the value in order to avoid server hyperactivity (excessive use of virtual memory on disk).
We will analyze the current configuration:
$ cat /etc/apache2/mods-enabled/mpm_prefork.conf
[ ... OUTPUT COUPÉ ... ]
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
[ ... OUTPUT COUPÉ ... ]
StartServers

MinSpareServers

The MinSpareServers directive sets the desired minimum number of inactive child server processes. An inactive process is a process that does not process a request. If there are fewer MinSpareServers inactive processes, the parent process will create new children in the following way: it creates one, waits for a second, creates two, waits for a second, creates four, and then continues exponentially until its child process creation rate is 32 per second. It stops only when the number of child processes matches the definition of the MinSpareServers directive. I will insist on the inactive process aspect! If you start your apache service, you will have 5 apache processes (outside the parent present to listen on the port)
$ ps aux | grep ^www-data
www-data 59 0.0 0.2 90588 5568 ? S 08:42 0:00 /usr/sbin/apache2 -k start
www-data 60 0.0 0.2 90588 5572 ? S 08:42 0:00 /usr/sbin/apache2 -k start
www-data 61 0.0 0.2 90588 5572 ? S 08:42 0:00 /usr/sbin/apache2 -k start
www-data 62 0.0 0.2 90588 5572 ? S 08:42 0:00 /usr/sbin/apache2 -k start
www-data 63 0.0 0.2 90588 5572 ? S 08:42 0:00 /usr/sbin/apache2 -k start
If you access the Server-status URL (https://www.linux202-sitea.com/server-status), you will see the current state of the processes
CPU Usage: u0 s0 cu0 cs0
0 requests/sec - 0 B/second -
1 requests currently being processed, 4 idle workers
1 Query pending 4 in expectation, but the MinSpareServers statement indicates that we must have 5 processes pending, effectively if you made the ps command you will have 6 apache processes running, the server-status URL will give you the same information .
MaxSpareServers

The MaxSpareServers directive sets the desired maximum number of inactive child server processes. An inactive process is a process that does not process a request. If there are more MaxSpareServers processes inactive, the parent process will stop the excess processes.
The modification of this parameter is only necessary in the case of highly stressed sites. Setting this parameter to a very large value is, however, in most cases a bad idea. In our case the minimum number is 5, if there is an excessive number of requests the system will start more processes to process the requests. Once the load is complete the apache will kill the idle processes over that number, however when the apache process number is equal to MaxSpareServers the system will leave them this will cause a memory usage to keep these processes.
MaxRequestWorkers (MaxClients avant la version 2.3.13)

The MaxRequestWorkers directive is used to set the maximum number of requests that can be processed simultaneously. If the MaxRequestWorkers limit is reached, any connection attempt will normally be queued up to a number that depends on the ListenBacklog directive. When a child process is released after the completion of a request, the pending connection can be processed in turn.
For non-threaded servers (that is, using prefork), the MaxRequestWorkers directive sets the maximum number of child processes that can be started simultaneously to process queries. The default value is 256; if you increase it, you must also increase the value of the ServerLimit directive.
MaxConnectionsPerChild

The MaxConnectionsPerChild directive sets the maximum number of connections that a child process will be able to process during its operation. When it processed MaxConnectionsPerChild connections, the child process is stopped. If MaxConnectionsPerChild is set to 0, there is no limit on the number of connections the process will handle.
Setting MaxConnectionsPerChild to a non-zero value limits the amount of memory a process can consume because of (accidental) memory leaks. It is therefore strongly recommended to define a value in order to have a process recycling.