Un Balanceador de carga fundamentalmente es un dispositivo de hardware o software que se pone al frente de un conjunto de servidores que atienden una aplicación y, tal como su nombre lo indica, asigna o balancea las solicitudes que llegan de los clientes a los servidores usando algún algoritmo (desde un simple round-robin hasta algoritmos más sofisticados).

 

Esquema en virtualbox o KVM

Es importante saber que la red externa (172.22.0.0/16) puede variar según nuestro direccionamiento.

Configuraciones previas en apache1 y apache2

Deshabilitar la opción KeepAlive en /etc/apache2/apache2.conf para realizar la evaluación del rendimiento sin la opción de reutilización de conexiones

root@apache1:~# cat /etc/apache2/apache2.conf

KeepAlive Off

root@apache2:~# cat /etc/apache2/apache2.conf

KeepAlive Off
Info! Este ajuste no es estrictamente necesario (y sería desaconsejable en un entorno de producción real), pero facilita las pruebas manuales dado que permite detectar inmediatamente el “cambio” de destino resultado del balanceo de carga manteniendo la opción por defecto, en las pruebas manuales desde el navegador sería necesario esperar 5 segundos (el time out de keep alive) antes de recargar la página y ver el efecto del reparto de carga.

Creamos los .html del sitio web

Debemos incluir una indicación del servidor real que está sirviendo una petición, de modo que sea posible “diferenciarlos” en las pruebas manuales con el navegador, por lo tanto seria asi:

Apache1

root@apache1:~# cat/var/www/html/index.html
 
 <h1> Servidor por APACHE_UNO </h1>

root@apache1:~# cat /var/www/html/sesion.php


 <?php
 header('Content-Type: text/plain');
 session_start();
 if(!isset($_SESSION['visit']))
 {
         echo "This is the first time you're visiting this server";
         $_SESSION['visit'] = 0;
 }
 else
         echo "Your number of visits: ".$_SESSION['visit'];

 $_SESSION['visit']++;

 echo "\nServer IP: ".$_SERVER['SERVER_ADDR'];
 echo "\nClient IP: ".$_SERVER['REMOTE_ADDR'];
 echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR']."\n";
 print_r($_COOKIE);
 ?>

Apache2

root@apache2:/~# nano /var/www/html/index.html

 <h1> Servidor por APACHE_DOS </h1>

Creamos sleep.php en ambas maquinas

 <html>
     <title> Retardos de x segundos </title>
 <body>
     <h1> Prueba con retardo de x segundos </h1>
     <p> hora de inicio: <?php echo date('h:i:s'); ?> </p>
     <?php
     for ($i=0; $i < 2000000; $i++) {
         $str1 = sha1(rand()*rand());
         $str2 = sha1(rand()*rand());
         $str3 = sha1($str1+$str2);
     }
     ?>
     <p> hora de fin: <?php echo date('h:i:s'); ?> </p>
 </body>
 </html>

Comprobación funcionamiento script

root@apache1:/home/usuario# php /var/www/html/sleep.php
 <html>
     <title> Retardos de x segundos </title>
 <body>
     <h1> Prueba con retardo de x segundos </h1>
     <p> hora de inicio: 01:20:36 </p>
          <p> hora de fin: 01:20:41 </p>
 </body>
 </html>
 

root@apache2:/home/usuario# php /var/www/html/sleep.php
 <html>
     <title> Retardos de x segundos </title>
 <body>
     <h1> Prueba con retardo de x segundos </h1>
     <p> hora de inicio: 01:20:49 </p>
          <p> hora de fin: 01:20:54 </p>
 </body>
 </html>

Evaluar rendimiento de Apache sin balanceo

Habilitar en balanceador la redirección de puertos para que sea accesible el servidor Apache de la máquina apache1 [10.10.10.11] empleando el siguiente comando iptables:

root@balanceador:~# echo 1 > /proc/sys/net/ipv4/ip_forward
root@balanceador:~# iptables -t nat -A PREROUTING --in-interface eth0 --protocol tcp --dport 80 -j DNAT --to-destination 10.10.10.11
Info! La regla iptables establece una redirección del puerto 80 de la máquina balanceador al mismo puerto de la máquina apache1 para el tráfico procedente de la red externa (interfaz de entrada eth0).

Y reiniciamos el servicio en apache1 systemctl restart apache2

E intentamos acceder desde el cliente con la ip del balanceador

Prueba contenido estatico

Para ello vamos a utilizar la herramienta Apache Benchmark

root@cliente:~# ab -n 2000 -c 10 http://192.168.1.41/index.html
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /index.html
Document Length:        35 bytes

Concurrency Level:      10
Time taken for tests:   1.371 seconds
Complete requests:      2000
Failed requests:        0
Total transferred:      562000 bytes
HTML transferred:       70000 bytes
Requests per second:    1458.27 [#/sec] (mean)
Time per request:       6.857 [ms] (mean)
Time per request:       0.686 [ms] (mean, across all concurrent requests)
Transfer rate:          400.17 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2   1.5      1      12
Processing:     1    5   2.2      5      23
Waiting:        1    4   2.1      4      23
Total:          3    7   2.5      6      29

Percentage of the requests served within a certain time (ms)
  50%      6
  66%      7
  75%      8
  80%      8
  90%     10
  95%     12
  98%     14
  99%     16
 100%     29 (longest request)
root@cliente:~# ab -n 2000 -c 50 http://192.168.1.41/index.html
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /index.html
Document Length:        35 bytes

Concurrency Level:      50
Time taken for tests:   1.333 seconds
Complete requests:      2000
Failed requests:        0
Total transferred:      562000 bytes
HTML transferred:       70000 bytes
Requests per second:    1500.33 [#/sec] (mean)
Time per request:       33.326 [ms] (mean)
Time per request:       0.667 [ms] (mean, across all concurrent requests)
Transfer rate:          411.71 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2   1.7      2      11
Processing:     6   31   5.7     31      62
Waiting:        6   30   5.6     30      60
Total:         12   33   5.2     33      65

Percentage of the requests served within a certain time (ms)
  50%     33
  66%     34
  75%     35
  80%     36
  90%     38
  95%     41
  98%     49
  99%     52
 100%     65 (longest request)
root@cliente:~# ab -n 2000 -c 100 http://192.168.1.41/index.html
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /index.html
Document Length:        35 bytes

Concurrency Level:      100
Time taken for tests:   1.334 seconds
Complete requests:      2000
Failed requests:        0
Total transferred:      562000 bytes
HTML transferred:       70000 bytes
Requests per second:    1499.37 [#/sec] (mean)
Time per request:       66.695 [ms] (mean)
Time per request:       0.667 [ms] (mean, across all concurrent requests)
Transfer rate:          411.45 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3   3.3      1      16
Processing:    11   62  10.7     63     103
Waiting:       10   62  10.6     62     102
Total:         27   65   9.0     65     104

Percentage of the requests served within a certain time (ms)
  50%     65
  66%     68
  75%     69
  80%     71
  90%     76
  95%     80
  98%     86
  99%     88
 100%    104 (longest request)

Esto envía 2000 peticiones HTTP sobre la URI “estática”, manteniendo, respectivamente, 10 y 50 conexiones concurrentes.

Prueba Scripts PHP

Se usará un script PHP (sleep.php) que introduce un retardo mediante un bucle “activo” de 2000000 interaciones que busca forzar el uso de CPU con cálculos de hashes SHA1 y concatenaciones de cadenas:

root@cliente:~# ab -n 250 -c 1 http://192.168.1.41/sleep.php
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /sleep.php
Document Length:        208 bytes

Concurrency Level:      1
Time taken for tests:   1373.348 seconds
Complete requests:      250
Failed requests:        0
Total transferred:      99750 bytes
HTML transferred:       52000 bytes
Requests per second:    0.18 [#/sec] (mean)
Time per request:       5493.393 [ms] (mean)
Time per request:       5493.393 [ms] (mean, across all concurrent requests)
Transfer rate:          0.07 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.2      1      14
Processing:  4799 5492 658.6   5297    9945
Waiting:     4799 5492 658.7   5296    9944
Total:       4800 5493 659.0   5297    9945

Percentage of the requests served within a certain time (ms)
  50%   5297
  66%   5484
  75%   5646
  80%   5830
  90%   6279
  95%   6920
  98%   7508
  99%   7823
 100%   9945 (longest request)

root@cliente:~# ab -n 250 -c 3 http://192.168.1.41/sleep.php
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /sleep.php
Document Length:        208 bytes

Concurrency Level:      3
Time taken for tests:   1208.840 seconds
Complete requests:      250
Failed requests:        0
Total transferred:      99750 bytes
HTML transferred:       52000 bytes
Requests per second:    0.21 [#/sec] (mean)
Time per request:       14506.075 [ms] (mean)
Time per request:       4835.358 [ms] (mean, across all concurrent requests)
Transfer rate:          0.08 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.2      1      13
Processing:  4747 14469 1058.5  14667   16624
Waiting:     4747 14465 1058.1  14667   16624
Total:       4747 14470 1058.5  14668   16625

Percentage of the requests served within a certain time (ms)
  50%  14668
  66%  15041
  75%  15149
  80%  15209
  90%  15611
  95%  16010
  98%  16326
  99%  16499
 100%  16625 (longest request)

root@cliente:~# ab -n 250 -c 5 http://192.168.1.41/sleep.php
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /sleep.php
Document Length:        208 bytes

Concurrency Level:      5
Time taken for tests:   1174.014 seconds
Complete requests:      250
Failed requests:        0
Total transferred:      99750 bytes
HTML transferred:       52000 bytes
Requests per second:    0.21 [#/sec] (mean)
Time per request:       23480.275 [ms] (mean)
Time per request:       4696.055 [ms] (mean, across all concurrent requests)
Transfer rate:          0.08 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.7      1       4
Processing: 22065 23474 1286.6  22913   28476
Waiting:    22064 23469 1286.8  22912   28476
Total:      22065 23475 1286.7  22914   28477

Percentage of the requests served within a certain time (ms)
  50%  22914
  66%  23488
  75%  24002
  80%  24151
  90%  25106
  95%  26095
  98%  28246
  99%  28337
 100%  28477 (longest request)

Envía 250 peticiones HTTP sobre la URI “dinámica”, esto puede tardar aprox entre 5-7 minutos.

Configurar y evaluar balanceo de carga con dos servidores

Primero vemos las reglas iptables, es decir, la regla creada anteriormente iptables -L PREROUTING -t nat y eliminamos las reglas iptables -t nat -F

Instalamos haproxy en la maquina balanceador apt install haproxy

Configurar HAproxy en balanceador (Sin soporte de sesiones persistentes)

root@balanceador:~# cd /etc/haproxy/
root@balanceador:/etc/haproxy# mv haproxy.cfg haproxy.cfg.original
root@balanceador:/etc/haproxy# nano haproxy.cfg

global
    daemon
    maxconn 256
    user    haproxy
    group   haproxy
    log     127.0.0.1       local0
    log     127.0.0.1       local1  notice

defaults
    mode    http
    log     global
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms

listen granja_cda
    bind 192.168.1.41:80 #IP_BALANCEADOR
    mode http
    stats enable
    stats auth  cda:cda
    balance roundrobin
    server uno 10.10.10.11:80 maxconn 128
    server dos 10.10.10.22:80 maxconn 128

Y reiniciamos el servicio systemctl restart haproxy.service

Comprobacion funcionamiento balanceador

Una vez reiniciado, vamos a realizar las pruebas para ello vamos a utilizar apt install w3m desde el cliente y accedemos con la ip del balanceador w3m 192.168.1.41 podemos comprobar que si recargamos o accedemos, salimos y accedemos la pagina ha cambiado entre los dos servidores apache configurados.

Pruebas de balanceador de carga

Carga sin balanceador

root@cliente:~# ab -n 250 -c 1 http://192.168.1.41/sleep.php
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /sleep.php
Document Length:        208 bytes

Concurrency Level:      1
Time taken for tests:   1373.348 seconds
Complete requests:      250
Failed requests:        0
Total transferred:      99750 bytes
HTML transferred:       52000 bytes
Requests per second:    0.18 [#/sec] (mean)
Time per request:       5493.393 [ms] (mean)
Time per request:       5493.393 [ms] (mean, across all concurrent requests)
Transfer rate:          0.07 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.2      1      14
Processing:  4799 5492 658.6   5297    9945
Waiting:     4799 5492 658.7   5296    9944
Total:       4800 5493 659.0   5297    9945

Percentage of the requests served within a certain time (ms)
  50%   5297
  66%   5484
  75%   5646
  80%   5830
  90%   6279
  95%   6920
  98%   7508
  99%   7823
 100%   9945 (longest request)

Carga con el balanceador de carga iniciado

root@cliente:~# ab -n 30 -c 10 http://192.168.1.41/sleep.php
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.1.41 (be patient).....done


Server Software:        Apache/2.4.10
Server Hostname:        192.168.1.41
Server Port:            80

Document Path:          /sleep.php
Document Length:        208 bytes

Concurrency Level:      10
Time taken for tests:   82.917 seconds
Complete requests:      30
Failed requests:        0
Total transferred:      11970 bytes
HTML transferred:       6240 bytes
Requests per second:    0.36 [#/sec] (mean)
Time per request:       27639.048 [ms] (mean)
Time per request:       2763.905 [ms] (mean, across all concurrent requests)
Transfer rate:          0.14 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   1.0      1       3
Processing: 25976 27443 1031.2  27389   29975
Waiting:    25976 27443 1031.2  27389   29975
Total:      25977 27444 1030.8  27391   29976

Percentage of the requests served within a certain time (ms)
  50%  27391
  66%  27911
  75%  28222
  80%  28407
  90%  28692
  95%  29485
  98%  29976
  99%  29976
 100%  29976 (longest request)

Podemos observar como al realizar la prueba con el balanceador de carga instalado como se reduce el tiempo de respuesta y como baja la media dado a que empieza a repartir las peticiones a uno y otro servidor.

Estadísticas haproxy

Podemos obtener una representación de las estadísticas del balanceador HAProxy (pedirá un usuario y un password, ambos cda)