Recursos complementarios
En estas prácticas se empleará el software de virtualización VIRTUALBOX para simular los equipos GNU/Linux sobre los que se realizarán las pruebas.
alumno@pc: $ sh ejercicio-haproxy.sh
Powershell.exe -executionpolicy bypass -file ejercicio-haproxy.ps1
Notas:
$DIR_BASE
especifica donde se descargarán las imágenes y se crearán las MVs.
Por defecto en GNU/Linux será en $HOME/CDA2223 y en Windows en C:/CDA2223.
Puede modificarse antes de lanzar los scripts para hacer la instalación en otro directorio más conveniente (disco externo, etc)
.vdi.zip
de http://ccia.esei.uvigo.es/docencia/CDA/2223/practicas/ y copiarlos en el directorio anterior ($DIR_BASE
) para que el script haga el resto.
VBoxManage startvm <nombre MV>_<id>
Contiene un sistema Debian 11 con herramientas gráficas y un entorno gráfico ligero LXDE (Lighweight X11 Desktop Environment) [LXDE].
login | password |
---|---|
root | purple |
usuario | usuario |
(con permisos para sudo ) |
root@datos:~# startx
Dispositivos -> Portapapeles compartido -> bidireccional
de la ventana de la máquina virtual.
Nota: para hacer más evidente el efecto del balanceo de carga, la capacidad de uso de la CPU en las dos máquinas del cluster de balanceo de carga (apache1 y apache2) está reducida al 30%.
HAProxy es un balanceador de carga que funciona como un proxy inverso (reverse proxy) repartiendo las conexiones recibidas de los clientes entre un conjunto de ”servidores reales”.
cliente <-> HAproxy
y HAproxy <-> servidor real
, sobre las que retransmite los mensajes de petición y respuesta
cliente
el balanceador HAproxy
decide a cúal de los servidores reales
se retransmitirá el tráfico de esa nueva conexión
servidor real
cliente <-> HAproxy
, Haproxy <-> servidor real
) en ambos sentidos mientras la conexión con el cliente
esté establecida
Funcionalidades
Detalles en http://docs.haproxy.org/2.2/intro.html3
Configuración por defecto en /etc/haproxy/haproxy.cfg
Fichero de configuración organizado en secciones
user, group, chroot, setenv, ...
ca-base, ssl-default-xxx-xxx, ...
maxconn, tune.buffers.xxx, ...
mode
(tipo de proxy http
ó tcp
), timeouts, etc
frontend
(pueden definirse varios)
bind [<address>]:<port_range>
: define uno (o varios) puertos de escucha (opcionalmente también dirección IP) de un proxy inverso / balanceador
stats enable|auth|admin|scope|uri|...
: configuración de la página de estadísticas del proxy
default-backend
: nombre del backend al que por defecto se redigirán las conexiones recibidas (excepto las que se controlen mediante use_backend
)
use_backend <nombre> if|unless <condicion>
: especifica el backend
que atenderá las conexiones indicadas
en las ACL que indique la <condicion>
acl <nombre> <criterio> <valor>
: declara una lista de control y la condición sobre un criterio (src, src_port, hdr(...), ...
) que debe cumplir una conexión
backend
(pueden definirse varios)
servidores reales
a donde serán reenviadas las conexiones de los clientes ”balanceadas” por HAProxy
balance <algorithm>
: algoritmo usado para seleccionar el serividor real a usar en cada nueva conexión (roundrobin, leastconn, first, source, uri,...
)
server <name> <address>[:port] [settings ...]
: definición de cada uno de los servidores reales del backend
cookie <name> rewrite|insert|prefix ...
: habilita la ”persistencia de conexiones/sesiones” basada en el seguimiento de la cookie con el nombre indicado.
frontend
y un backend
para describir un proxy inverso completo.
Detalles en http://docs.haproxy.org/2.2/configuration.html#2
cliente:~# startx
apache1:~# nano /etc/apache2/apache2.conf ... KeepAlive Off ...
apache2:~# nano /etc/apache2/apache2.conf ... KeepAlive Off ...
Nota:
apache1:~# nano /var/www/html/index.html ... <h1> Servidor por APACHE_UNO </h1> ...
apache1:~# nano /var/www/html/sesion.php ... <h1> Servido por APACHE_UNO </h1> ...
apache2:~# nano /var/www/html/index.html ... <h1> Servido por APACHE_DOS </h1> ...
apache2:~# nano /var/www/html/sesion.php ... <h1> Servido por APACHE_DOS </h1> ...
Notas:
apache1~:# nano /var/www/html/sleep.php apache2~:# nano /var/www/html/sleep.php
Nuevo contenido (reemplaza el existente)
<html> <title> Página dinámica con retardo </title> <body> <h1> Prueba dinámica con retardo </h1> <p> hora de inicio: <?php echo date('h:i:s'); ?> </p> <?php for ($i=0; $i < 100000; $i++) { // <- poner 100000 iteraciones $str1 = sha1(rand()*rand()); // <- tres llamadas a sha1() $str2 = sha1(rand()*rand()); $str3 = sha1(rand()*rand()); } ?> <p> hora de fin: <?php echo date('h:i:s'); ?> </p> </body> </html>
Comprobación
apache1~:# php /var/www/sleep.php apache2~:# php /var/www/sleep.php
Se realizarán varias pruebas de carga sobre el servidor Apache ubicado en la máquina apache1 para determinar el rendimiento que puede llegar a ofrecer una instancia única del servidor Apache.
Pasos a realizar
balanceador:~# systemctl stop haproxy
balanceador:~# systemctl stop apache2
Nota: En ocasiones no tiene efecto la parada del servicio apache2, puede comprobarse si el proceso sigue en ejecución con pidof apache2 y ”matar” los posibles procesos supervivientes si fuera necesario.
balanceador:~# pidof apache2 wwww xxxx yyyy zzzz balanceador:~# kill -9 wwww xxxx yyyy zzzz
balanceador:~# echo 1 > /proc/sys/net/ipv4/ip_forward balanceador:~# iptables -P FORWARD ACCEPT balanceador:~# iptables -t nat -A PREROUTING \ --in-interface enp0s3 --protocol tcp --dport 80 \ -j DNAT --to-destination 10.10.10.11
Notas:
iptables
establece una política de aceptar por defecto en la cadena FORWARD
Normalmente esta regla no sería necesaria (por defecto el kernel arranca con una política ”aceptar por defecto” en todas las cadenas),
pero en este caso la instalación de Docker en la MV estableció un DROP
por defecto en la
cadena FORWARD
que impediría el tráfico del ejercicio.
apache1:~# systemctl restart apache2 #(ó systemctl start apache2)
Comprobación:
http://193.147.87.47
en el navegador web Falkon o en el navegador en modo texto lynx
.
cliente:~# lynx 193.147.87.47Usar la tecla
Q
o [Control]+C
para salir de lynx
APACHE_uno
.
Pruebas a realizar:
cliente:~# ab -n 2000 -c 10 http://193.147.87.47/index.html cliente:~# ab -n 2000 -c 50 http://193.147.87.47/index.html
Envía 2000 peticiones HTTP (opción -n
) sobre la URI ”estática” index.html, realizando, respectivamente, 10 y 50 conexiones concurrentes (opción -c
). ( 1 minuto)
Pruebas a realizar:
cliente:~# ab -n 250 -c 10 http://193.147.87.47/sleep.php cliente:~# ab -n 250 -c 30 http://193.147.87.47/sleep.phpEnvía 250 peticiones HTTP sobre la URI ”dinámica”, realizando, respectivamente, 10 y 30 conexiones concurrentes. (aprox 3-4 minutos)
En cada ejecución del comando ab se muestran las estadísticas obtenidas. Para el tipo de prueba informal que se realiza en este ejemplo, basta prestar atención a los parámetros Requests per second (num. peticiones por segundo) ó Time per request (tiempo en milisegundos para procesar cada petición).
balanceador:~# iptables -t nat -F balanceador:~# iptables -t nat -Z
balanceador:~# systemctl stop apache2
apache1:~# systemctl restart apache2 #(ó systemctl start apache2) apache2:~# systemctl restart apache2 #(ó systemctl start apache2)
balanceador:~# apt-get update balanceador:~# apt-get install haproxy
balanceador:~# cd /etc/haproxy balanceador:/etc/haproxy/# mv haproxy.cfg haproxy.cfg.original balanceador:/etc/haproxy/# nano haproxy.cfg
Contenido a incluir:
global daemon maxconn 256 user haproxy group haproxy defaults mode http log global timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend web_cda bind 193.147.87.47:80 mode http stats enable stats auth cda:cda default_backend servidores_cda backend servidores_cda balance roundrobin server uno 10.10.10.11:80 maxconn 128 server dos 10.10.10.22:80 maxconn 128
Define (en la sección frontend) un ”proxy inverso” de nombre web_cda que:
servidores_cda
backend
) la lista de servidores reales servidores_cda
Más detalles en Opciones de configuración HAPproxy 2.2
Antes de hacerlo es necesario habilitar en /etc/default/haproxy el arranque de HAproxy desde los scripts de inicio de Debian, estableciendo la variable ENABLED=1
balanceador:/etc/haproxy/# nano /etc/default/haproxy ... ENABLED=1
Inicio empleando el script de arranque de HAproxy (preferente)
balanceador:/etc/haproxy/# systemctl stop haproxy # ya estaba arrancado balanceador:/etc/haproxy/# systemctl start haproxy
balanceador:/etc/haproxy/# haproxy -d -V -f /etc/haproxy/haproxy.cfg
lynx
y recargar varias veces con [Control]+R
para comprobar como cambia el servidor real que responde las peticiones.
cliente:~# lynx 193.147.87.47Nota: El navegador gráfico Falkon hace caché de las páginas cargadas y no permite comprobar el balanceo de carga directamente recargando la página.
Nota: Si no se ha deshabilitado la opción KeepAlive de Apache, es necesario esperar 5 segundos entre las recargas para que se agote el tiempo de espera para cerrar completamente la conexión HTTP y que pase a ser atendida por otro servidor.
Pruebas a realizar:
cliente:~# ab -n 2000 -c 10 http://193.147.87.47/index.html cliente:~# ab -n 2000 -c 50 http://193.147.87.47/index.html cliente:~# ab -n 250 -c 10 http://193.147.87.47/sleep.php cliente:~# ab -n 250 -c 30 http://193.147.87.47/sleep.php
Los resultados deberían de ser mejores que con la prueba anterior con un servidor Apache único (al menos en el caso del script sleep.php)
apache1:~# tail /var/log/apache2/error.log apache2:~# tail /var/log/apache2/error.log apache1:~# tail /var/log/apache2/access.log apache2:~# tail /var/log/apache2/access.log
Comprobar el contenido del fichero PHP /var/www/html/sesion.php
disponible en las máquinas apache1 [10.10.10.11] y apache2 [10.10.10.22].
Se puede verificar el funcionamiento ”defectuoso” del balanceo de carga por defecto (round robin sin seguimiento de cookies
), accediendo desde la máquina cliente a la URL http://193.147.87.47/sesion.php
con el navegador en modo texto lynx
y recargando la página varias veces con [Control]+R
.
cliente:~# lynx -accept-all-cookies http://193.147.87.47/sesion.php
SET_COOKIE
donde se establece el nombre y el valor de la Cookie)
COOKIE
de la cabecera de la petición HTTP) serán enviadas únicamente el servidor que estableció esa Cookie, ”desactivando” en ese caso el reparto de carga que realizaría el balanceador
Para solucionarlo es necesario configurar HAProxy para que haga el seguimiento de las cookies de sesión. De tal modo que no se aplique el balanceo de carga, asignado el mismo servidor real que estableció una cookie determinada en un parámetro SET_COOKIE
de una HTTP response
.
balanceador:/etc/haproxy/# systemctl stop haproxy
balanceador:~# nano /etc/haproxy/haproxy.cfg
Contenido a incluir: (añadidos marcados con <- aqui)
global daemon maxconn 256 user haproxy group haproxy defaults mode http log global timeout connect 10000ms timeout client 50000ms timeout server 50000ms frontend web_cda bind 193.147.87.47:80 mode http stats enable stats auth cda:cda default_backend servidores_cda backend servidores_cda balance roundrobin cookie PHPSESSID prefix # <- aqui server uno 10.10.10.11:80 cookie ZIPI maxconn 128 # <- aqui server dos 10.10.10.22:80 cookie ZAPE maxconn 128 # <- aqui
El parámetro cookie especifica el nombre de la cookie que se usa como identificador único de la sesión del cliente (en el caso de aplicaciones web PHP se suele utilizar por defecto el nombre PHPSESSID)
ZIPI
y ZAPE
en el ejemplo)
prefix
SET_COOKIE
establece la Cookie de sesión, el cliente recibirá como valor de la Cookie el valor de la Cookie original precedido de la etiqueta del servidor que la haya establecido
[etiqueta servidor]~[cookie original]
[cookie original]
balanceador:/etc/haproxy/# systemctl start haproxy
cliente:~# wireshark &
cliente:~# lynx -accept-all-cookies http://193.147.87.47/sesion.php
[control]+R
)
Verificar la estructura y valores de las cookies PHPSESSID intercambiadas
Entrega: MOOVI (práctica individual)
Fecha límite: hasta el domingo 27/11/2022