Hay muchas maneras pero dejamos dos simples. Es necesario por motivos obvios, conocer la versión de apache instalada en nuestro sistema y el modo en el que ha sido compilado.
1 | <strong># httpd -v</strong> |
Output:
1 2 | -bash-3.1# Server version: Apache/2.2.3 -bash-3.1# Server built: John 15 2008 20:33:30 |
1 | <strong># httpd -l</strong> |
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
De esta manera sabemos que estamos ante un servidor Apache / 2.2.3 y en modo prefork:
Prefork MPM: el modo prefork utiliza múltiples procesos hijo, cada proceso hijo se ocupa de una conexión a la vez. Prefork es muy adecuado para sistemas con doble CPU, la velocidad es comparable al del Worker MPM y es altamente tolerante con los fallos en los módulos y los procesos hijos colgados. Por contra, el uso de memoria es alto y cuanto más tráfico tenemos más memoria consume
Worker MPM: utiliza múltiples procesos hijo. Es multi-thread dentro de cada proceso hijo y cada thread se encarga de una conexión. Worker es más rápido y escalable y el uso de memoria es comparativamente bajo. Es también adecuado para múltiples procesadores. Worker es menos tolerante ante fallos de módulos y un fallo en un thread puede afectar a todos los threads de un proceso hijo.
Este Módulo de MultiProcesamiento (MPM) implementa un servidor híbrido multiproceso-multihebra. Usando hebras para atender peticiones, el servidor puede servir un mayor número de peticiones con menos recursos de sistema que un servidor basado únicamente en procesos. No obtante, se mantiene casi por completo la estabilidad de un servidor basado en procesos manteniendo la capacidad multiproceso, pudiendo cada proceso tener muchas hebras.
Directivas de Apache
- MaxClients: es el número total de procesos hijo httpd que pueden ser procesados simultáneamente. El valor por defecto es bastante elevado para la mayoría de servidores (256). Cada proceso hijo es capaz de mapear (allocate) memory in a number of information X. And Drupal, for example, each process may use a 10-15 MB of memory. 20 processes, 20MB of RAM for each, consume cerca de 500MB de memoria física. Cuando nos acercamos o llegamos al límite marcado, apache no devuelve un TimeOut inmediato, sino que coloca la petición en cola. Una aproximación racional al número adecuado para esta directiva podría ser la división de la cantidad total de RAM disponible (dejando una generosa cantidad para otros procesos) entre el máximo tamaño del proceso apache. Podemos saber el consumo de memoria de apache por proceso con el comando ps.
Lo fundamental para entender como gestionar la directiva MaxClients, es comprender que puede tener un valor “alto” sino nuestro servidor está sirviendo contenido estático, pero con aplicaciones modernas tipo PHP de contenido dinámico, podemos tener graves problemas de estabilidad si no calculamos bien el número total de MaxClients. Una fórmula para calcular el valor apropiado del MaxClients sería (hay muchas) la siguiente:
MaxClients = Total RAM dedicated to the web server / Max child process size
En un ejemplo práctico, tenemos una máquina virtual (OpenVZ) con 1Gb de RAM asignado. Después de averiguar el tamaño total del proceso apache, dividimos:
1 GB (1024 MB) / 2,3 MB = 445 MaxClients
Siempre pensando en un servidor que “sólo” ejecutara apache, obviously, este valor es sólo un ejemplo. Nunca se debería asumir esa cantidad total de MaxClients. Lo mejor sería aumentar un poco el valor y comprobar el funcionamiento del servidor. Pero sería un buen punto de referencia.
- StartServers: número de procesos iniciales.
- MinSpareServers: número de procesos iniciales en iddle que esperan una petición.
- MaxSpareServers: número máximo de procesos en iddle esperando.
- MaxRequestsPerChild: cuando un proceso excede este valor, el proceso es destruido y, si es necesario, un nuevo proceso lo reemplaza. Esto puede reducir la memoria total usada en muchas situaciones, con los archivos dinámicos incrementando constantemente su uso de RAM y reiniciando los procesos para reducir su uso.
- ServerLimit: si nosotros queremos aumentar el número total de MaxClients de 256 a 300, debemos en principio aumentar el ServerLimit a la misma cantidad. Sino, el apache se quejará mostrándolo por la salida estándar.
- KeepAlive: por defecto está en off. Al estar on, permitimos a una misma conexión TCP hacer múltiples peticiones sin descartar la conexión (conexiones persistentes).
- MaxKeepAliveRequests: el número total de peticiones permitidas por una misma conexión TCP.
- KeepAliveTimeOut: el número máximo de segundos que permanecerá el proceso esperando a ser respondido.
Ejemplo configuración por defecto de Apache (La ruta de configuración etc/httpd/conf/httpd.conf)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # IfModule prefork.c StartServers 8 MinSpareServers 5 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000 # IfModule # IfModule worker.c StartServers 2 MaxClients 150 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 # ifModule |
Calcular memoria consumida por Apache
1 | <strong># ps -ylC httpd –black:rss </strong> |
–sort rss (lista ordenando por RSS(Resident Set Size), kb del proceso en memoria)
Output:
1 | <strong># S 48 5674 17426 0 75 0 2904 2637 277588 ? 00:00:00 httpd</strong> |
2904 / 1024 = 2,8 MB ocupados por proceso de Apache. Now, debemos saber el número total de procesos:
1 | # <strong>lsof -i | grep httpd | grep ESTABLISHED | wc -l</strong> |
Output:
# 15
De este modo, tenemos que por proceso utilizamos 2,8 MB de memoria (no swap). Y sabemos que hay 15 procesos de apache en memoria, con lo cual 2,8 MB x 15 = 42 MB usados. Otra forma, quizá más fácil de calcular como está rindiendo nuestro apache, es utilizar este script escrito en python (gracias al admin de Devside ) Os dejo un output de lo que muestra el script:
Private + Shared = RAM used Program
84.0 KiB + 312.0 KiB = 396.0 KiB klogd
128.0 KiB + 452.0 KiB = 580.0 KiB syslogd
128.0 KiB + 524.0 KiB = 652.0 KiB init
824.0 KiB + 600.0 KiB = 1.4 MiB bash
568.0 KiB + 1.1 MiB = 1.6 MiB sftp-server
1.6 MiB + 1.9 MiB = 3.5 MiB sshd (3)
37.4 MiB + 2.1 MiB = 39.5 MiB httpd (180)
Optimización
No hablaremos de optimización totalmente pero, si comentaremos que una de las cosas que se recomiendan por toda la comunidad es deshabilitar los módulos de apache que no necesitemos. En el ejemplo que me ocupa, una máquina virtual de 1GB de RAM de OpenVZ, deshabilitamos de 52 processes 35, dejando sólo activos 17. Volvimos a hacer el calculo de la memoria utilizada por apache entonces:
2,3 MB por proceso x 12 procesos = 33,6 MB! (22 % menos en memoria). No está mal.
Otro consejo que se da en todos los manuales de tunning de Apache, es el deshabilitar la resolución de DNS, HostnameLookups. Esta directiva intenta resolver cada IP conectada a tu servidor y eso genera un consumo de recursos innecesario.
Conexiones Persistentes
En sus inicios, el protocolo HTTP no permitía las conexiones persistentes, lo que significaba que era necesaria una conexión al servidor por cada archivo que tuviese que ser descargado. Esto era una manera ineficiente de hacer las cosas, especialmente desde que Internet comenzó a tener sitios webs con gran cantidad de archivos. ¿Por qué?:
- Cada conexión requiere la carga de al menos, 3 paquetes para ser iniciada (SYN,SYN-ACK,ACK). Esto significa que al menos 3 viajes de ida y vuelta para abrir una conexión.
- Dada la naturaleza de TCP, bajo protocolo HTTP, una conexión funciona más rápido cuanto más tiempo está “abierta”. El cerrar y abrir continuamente conexiones, no permite a HTTP utilizar su ancho de banda total.
Directivas de KeepAlive
- KeepAlive: habilita o deshabilita las conexiones persistentes [ On – Off]
- KeepAliveTimeout: cuanto tardará Apache, en segundos, después de que una petición haya sido respondida para pasar a otra antes de cerrar la conexión.
- MaxKeepAliveRequests: el número total de peticiones que se permite a una conexión abierta.
Cuando un cliente se conecta al servidor web, se le permite realizar múltiples peticiones en la misma conexión TCP, lo cual reduce la latencia asociada a las múltiples conexiones. Esto es útil cuando, for example, una conexión a una página web requiere varias imágenes, y todas esas imágenes son recibidas por el cliente en una misma conexión. El lado malo es que cada proceso o worker en el servidor debe esperar a que se cierre la sesión por el cliente antes de poder resolver la siguiente conexión. Es difícil decir si es adecuado o no, activar las conexiones persistentes. En caso de que lo activemos, debemos dejar un valor muy bajo, 2, en la directiva KeepAliveTimeout. De esta manera, nos aseguramos de que cualquier cliente puede hacer las peticiones con bastante tiempo, y que el proceso no estará esperando eternamente a que el cliente cierre la conexión y se moverá a la siguiente conexión TCP. Resumiendo, sólo podemos probar su uso y ver si responde a nuestras necesidades.
Una curiosidad. Después de activar el KeepAlive, lo pude ver reflejado al instante en las gráficas del Cacti.
Un poco después de las 16.00 hice el cambio y se puede ver perfectamente. Es lo bueno de tener herramientas como esta. Era viernes y como no es bueno hacer cambios en fin de semana, lo desactivé.
Last, comentar que la compresión de Apache logra muy buenos resultados. Revisar mod_deflate.
SOURCES: http://www.rubenortiz.es/2008/05/13/apache-maxclients-y-mas/