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).

$ 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
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 …
[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:

[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
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:
[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

 
Defines the number of processes that will start when the service is initialized, with the preforf module the default value is 5. This value is usually quite low, the goal is to be able to respond to the first queries quickly, thereafter when mounted in charge it will be the * SparesServers directive that will take over.

 

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