Hoy vengo a hablaros una vez más de uno de los servicios web más usados en todo el mundo: El servidor web Apache2.
Se trata de un tema del que se ha hablado multitud de veces, pero ahora vengo a hablaros de otra característica muy a tener en cuenta con este servicio: El límite de conexiones simultáneas. No importa si tenemos muy básico o una nave espacial con un procesador i7 y 32 GB de ram…
El límite de conexiones simultáneas siempre será el mismo a menos que tomemos las medidas adecuadas, lo que significa que si queremos tener muchas personas conectadas al mismo tiempo, no solo requeriremos un buen hardware, sino que también una buena configuración.
En este caso no es necesario instalar nada, todo se basa en simples conceptos que hay que tener en cuenta para configurar apache; conceptos que hay que tener muy claros antes de querer hacer cualquier cambio.
Lo primero que habría que pensar es: ¿Qué capacidad tiene mi equipo? ¿Cuantas conexiones simultáneas puede llegar a soportar mi equipo si lo llego a forzar el máximo posible? Todo esto depende de un único factor; la memoria RAM (Random Access Memory).
A mayor la memoria RAM, mayor el número de conexiones, si bien no existe un valor fijo (es decir X clientes por cada X ram), es por ello que antes de nada es importante hacer unos pequeños cálculos en nuestro servidor web, con el fin de conocer nuestros límites.
Lo primero que habría que saber es cuanta memoria RAM de media consume cada conexión a Apache, ya que cada conexión establecida supone un cierto consumo de RAM en el sistema… Obviamente no todas las conexiones consumen la misma ram, con lo que habría que hacer una media… Todo ello se puede obtener con el siguiente comando:
ps -ylC apache2 --sort:rss | awk '{SUM += $8; I += 1} END {print SUM/I/1024}'
El resultado obtenido estaría representado en megabytes y puede variar dependiendo del número de conexiones activas, el tipo de páginas a las que se accede, etc… Por ello es recomendable realizar la prueba con diferentes pestañas abiertas; cada una de ellas mostrando distintos contenidos a ser posible. En mi caso por ejemplo el resultado ha sido de 9.5458 lo que si lo redondeamos al superior serían 10 MB de RAM consumidos de media por conexión.
Además es importante saber cuanta memoria RAM es consumida por el resto de procesos que hay activos en el sistema, ya que el servicio web no es el único que corre en el sistema operativo y es necesario dejar memoria RAM libre en el servidor para que pueda ejecutar el resto de tareas. Esto se puede obtener con el comando mostrado a continuación:
ps -N -ylC apache2 --sort:rss | awk '{SUM += $8} END {print SUM/1024}'
El resultado obtenido también sería representado en megabytes, y nos mostraría con bastante precisión la cantidad de RAM consumida por el resto de procesos; en mi caso 800 MB. Con esta información podríamos hacer un calculo general de la cantidad de conexiones simultáneas que podríamos tener; calculo que obtendríamos mediante una operación bien sencilla.
(RAMTOTAL – RAM_RESTOPROCESOS) / RAM_POR_CONEXIÓN
Con esta formula en mano, imaginemos que tenemos un equipo con 4 GB RAM, es decir 4096 MB y que nuestro equipo a mostrado los resultados antes mencionados; el cálculo sería:
(4096 – 800)/10= 329 conexiones simultáneas
El problema con este calculo es que uno demasiado extremista, ya que nos consumiría toda la RAM (haciendo que el servidor consuma swap) y además, en caso de tener una base datos, como MySQL o cualquier otra, las conexiones a ésta también consumirían RAM, con lo que el número obtenido se podría calificar como un número utópico. Por ello, para dejar libre la memoria para posibles procesos adicionales y además contemplar la posibilidad de que se ejecuten conexiones a alguna base de datos, reduciríamos el número de conexiones a 250.
Ahora que tenemos nuestro número de conexiones simultáneas máximas, habría que preparar Apache para poder recibir dicho número, lo cual se realiza en el fichero de configuración de este llamado apache2.conf, el cual está alojado en /etc/apache2.
El fichero en cuestión sigue una estructura basada en módulos, cada uno con su nombre correspondiente, pero solamente nos interesaría uno de ellos, cuyo nombre es mpm_prefork_module. El módulo en cuestión posee los siguientes datos por defecto:
<IfModule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 150 MaxRequestsPerChild 0 </IfModule>
Este módulo posee una serie de parámetros muy importantes, aunque hay uno de ellos que nos interesaría especialmente, llamado MaxClients. Dicho parámetro especifica el número máximo de conexiones simultáneas y habría que modificarlo a 250.
Un detalle a tener en cuenta es que cuando se especifica un valor distinto al de por defecto en dicho parámetro, es necesario añadir otro más justo ANTES de éste. Dicho parámetro se denomina ServerLimit y establece el límite de conexiones que podría «aguantar» el servidor aún cuando se encuentra fuera del límite.
El parámetro ServerLimit siempre tiene que ser ligeramente superior al MaxClients y aquí al tener poco margen de maniobra habría que establecer un límite de 270. Esto haría que el módulo quedase de la siguiente forma:
<IfModule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 ServerLimit 270 MaxClients 250 MaxRequestsPerChild 0 </IfModule>
Ahora únicamente faltaría reiniciar el servicio Apache mediante el comando:
/etc/init.d/apache2 restart
Con esto ya podríamos disfrutar de nuestro servidor web optimizado.
Saludos.
¡Gracias por el post!
Me alegro que te haya resultado útil.
Saludos.
Existe una forma de hacer cluster con Apache y dos servidores, puedes explicar como funciona??
Aunque he leído algo de teoría al respecto, nunca lo he aplicado a la práctica. Aún así, tal vez este artículo te pueda dar alguna guía al respecto, aunque repito que no he tenido la oportunidad de pasarlo a la práctica:
http://www.muspells.net/blog/2011/04/alta-disponibilidad-con-apache2-y-heartbeat-en-debian-squeeze/
ya tiene rato que preguntaste, si no solucionaste; yo tengo un esquema de balanceo con un tercero que funge como file system, apuntas las carpetas que estan en var/www/html/ (en mi caso) al file system, así comparten la misma información, y posiblemente requeriras una ip virtual que responda y redireccione a las ips del los apaches, para esto puedes ocupar un haproxy y si lo quieres en alta disponibilidad puedes integrarle keepalive por si alguno se cae el otro siga respondiendo, o también si ya cuentas con dominio para la aplicacion, puedes balancear con pound haciendo backends hacia ambos servidores, para casos específicos como moodle o ciertas aplicaciones que conectan con base de datos en mysql, tendrias que crear un usuario por servidor de app que apunte a la misma base.
muchas gracias por el post, tiene todo la razón la ram es el calculo primordial, aunque me imagino que calcular tambien la cantidad máxima de procesos que puede manejar nuestro procesador (claro primero haciendo el calculo de la memoria principal) y como estaría distribuido el disco duro (particiones Ejemplo /var = 1TR).
Te doy toda la razón; todo es importante, al igual que el control de la temperatura entre otras cosas. Obviamente un procesador potente puede ejecutar un mayor número de tareas simultaneamente con mucha eficiencia, pero el objetivo de este post era explicar la importancia de que tiene la RAM con respecto al número de conexiones simultáneas.
Una buena forma de controlar todos estos factores y ver si nuestro procesador no está saturado o si nos queda poca RAM libre, sería mediante el uso de un script en bash. Tal vez te sea interesante este post que hice hace unos días al respecto que te dejo en el siguiente enlace; se trata de una monitorización global pero que puede resultarle a uno interesante:
http://bytelearning.blogspot.com.es/2015/07/controlando-la-salud-del-equipo-con-bash.html
Saludos
Muy buena la nota, muchas gracias!
Muchas gracias! Espero que hayas podido sacarle provecho.
no quiero ser un cretino…
…pero al aumentar la cantidad de conexiones no dejas mas vulnerable a un ataqur DDoS?
No es ninguna pregunta cretina tranquilo. Lo cierto es que aumentando el número de conexiones simultaneas, en parte fortificamos Apache contra los ataques DDOS, pues has de tener en cuenta que el número de conexiones simultaneas máximas establecidas en el servidor, son el número de conexiones máximas totales, no las procedentes de un solo usuario. Así pues, mientras que al principio solo podíamos soportar 150 conexiones simultaneas (ya sean conexiones de un origen legítimo o no) ahora podemos contar con tantas como nuestro servidor soporte, requiriendo un mayor número de conexiones al mismo tiempo para quedarse sin servicio. Obviamente el aumentar el número máximo de conexiones no es una forma de protegerse de este tipo de ataques sino que habría que implementar políticas de firewall. Si por ejemplo el servicio web que se quiere poner va a ser expuesto a internet, una medida de seguridad que se podría implementar sería la adición de estas líneas a nuestro cortafuegos:
iptables -A INPUT -p tcp –syn –dport 80 -m connlimit –connlimit-upto 10 -m state –state NEW -j ACCEPT
iptables -A INPUT -p tcp –dport 80 -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp –dport 80 -j DROP
una de las caracteristicas de los Ataques DDoS es que un atacante puede aparentar enviar paquetes desde varias direcciones distintas, lo que evita que el flujo de paquetes provenga solo de una dirección.
Tienes razón en el sentido de que un cortafuegos como el que he puesto no es demasiado eficiente contra un ataque DDOS, ya que proviene de distintos origines. Aún así, es mejor limitar el número de conexiones a 10 por cada uno de dichos origenes en vez de no tener un límite, haciendo que cada origen pueda establecer un centenar de conexiones o más.
De todas formas el kit de la cuestión es que cuantas más conexiones simultáneas soporte el servidor, más difícil será tumbarlo con un ataque DDOS, con lo que más que facilitar que la página sea tumbada por un atacante, lo dificultaría.
Saludos.
Buena. Por ahora sigo con NGINX en mi sitio para no torturar al VPS que tengo.
Buen post @Drassill!
Yo quería aportar con algo tal vez más estadístico que de configuración.
Si bien la forma más fácil y rápida de calcular el parámetro de consumo es con la media, a lo mejor podríamos ser mas rigurosos y usar la “mediana” en lugar de la “media”. De que nos salvaría? De que se nos disparen los números en caso de que una conexión haya consumido mucha memoria. Por ejemplo, supongamos los siguientes clientes que consumen los siguientes valores, en la unidad que quieran de memoria (KB, MB, MiB, etc):
10 , 15, 150, 5, 7, 10, 11, 12
La media daría aprox ~ 30
Y esto porque tenemos un extremo (150) muy grande, y que nos disparata los calculos. La mediana consiste en ordenar estos datos, dividir la cantidad de muestras por 2 (nuestro centro) y luego obtener el número de esa posición. Con esto tendríamos algo como
5, 7, 10 , 10, 11, 12, 15, 150
Entonces nuestra media sería: 8/2 = 4 osea ~10
Acá se ve, que no importa que tan disparate pueda ser el extremo, siempre nos dará un valor más realista. Si agregamos un cliente que consume 200, nuestra mediana sera 11, mientras que la media tal vez se nos vaya a …….
Es sólo un aporte, y es muy discutible, porque con las conexiones no se jode.
Abrazo gente linuxera 🙂
Hola he tenido un problema en mi servidor dedicado, y es que cada vez que se acerca la cantidad de 250 personas aproximadamente en linea, segun el google analytics en tiempo real, mi servido como que se colapsa y se pone lenta la conexion hasta se cae la conexion al sitio web y nunca sube mas de esa catidad de usuarios en linea, pero cuando veo el rendimiento del servidor dedicado que es de 8gb ram muestra 10% de uso, el cpu: 5% de uso y el disco duro en: 1.99% de uso.
Me puedes ayudar? no hallo que hacer, será que haciendo estos paso es la solución?
Buenas Carlos.
El problema que describes es muy común cuando no se tiene el servidor correctamente preparado. Probablemente tu servidor acepte una cantidad de conexiones simultáneas mucho menor y cuando llegue a la cifra de 250 conexiones se colapse. Siguiendo el manual deberías ser capaz de solventar el problema, si bien en caso de tener alguna base de datos en dicho servidor también tendrías que optimizar dicha base de datos.
Saludos.
Drassill, he hecho la configuración que mencionaste y ha resultado satisfactorio, ayer llegué a 280 usuarios en linea y no se colgó el servidor, me alegra mucho este resultado, y también quiero hacer lo otro que me dices en optimizar la base de datos, ¿como logro esto?
El concepto de base de datos es bastante abierto; no es lo mismo usar mysql que postgres (por ejemplo). Obviamente no conozco todas las bases de datos; he probado mysql y postgres, y el aumento de las conexiones simultáneas en éstas estaría basado en el parámetro max connections; la optimización de mysql se realizaría en /etc/my.conf y habría que cambiar (entre otros) el parámetro max connections. Para postgres en cambio, tengo un articulo en mi blog que explica cómo optimizarlo que tal vez te sea útil o que puedes usarlo como referencia para tu base de datos:
http://bytelearning.blogspot.com.es/2016/02/postgresql-una-alternativa-mysql-en.html
Saludos.
Hola, cuando arrojo el primer comando, me muestra valor 0. ¿Que podría ser?
Muchas gracias por este post.
Que buen manual, esa información es parte de lo que ando buscando… gracias!
Pero ahora, si yo quisiera que cuando se superan esos 250 visitantes, el visitante 251 vaya a parar a una página de espera o cola virtual puedo hacerlo desde esta misma configuración?
Saludos y gracias!