Conocer la versión
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: Jan 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
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, obviamente, 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.
Ejemplo configuración por defecto de Apache
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 --sort: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. Ahora, 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 procesos 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é?:
Directivas de KeepAlive
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, por ejemplo, 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é.
Por último, comentar que la compresión de Apache logra muy buenos resultados. Revisar mod_deflate.
Fuentes:
http://www.mysqlperformanceblog.com
http://www.mysqlperformanceblog.com/
http://www.devside.net/articles/apache-performance-tuning
http://www.onlamp.com/pub/a/onlamp/2004/02/05/lamp_tuning.html
http://www.pacosanchez.com/2007/11/21/optimizando-apache
http://httpd.apache.org/docs/2.0/mod/worker.html
http://httpd.apache.org/docs/2.0/mod/prefork.html
http://www.ibm.com/developerworks/web/library/l-tune-lamp-2.html#listing1
http://www.apache-es.org/?p=20
http://www.pixelbeat.org/scripts/ps_mem.py – Reporta la memoria consumida por el sistema
Muchas gracias por este artículo. Me ha servido mucho para entender un poco mas como funciona apache. Genial!
Hola tengo una aplicacion con ajax sobre apache, me sucede que cuando tengo continuas desconexiones, al encontrar medio la aplicación se recupera pero en determinado momento mi aplicacion se bloquea, como si apache rompiera el hilo de peticiones de ese cliente, en realidad no se que tan cerca estoy de lo que realmente sucede, me gustaria tu opinion, y siendo asi que parametro requiero mover en apache para corregirlo, gracias.
Hola Oscar
imposible decirte nada útil sobre tu problema, pueden ser mil cosas. De momento no soy tan bueno como para hacer un diágnostico de ese tipo : /
Mira los logs de apache y los logs que genere tu aplicación, sea PHP, Ruby, etc para buscar más información sobre tu problema.
Saludos
[...] Apache. MaxClients y más… [...]