systemadmin.es > LAMP y web > Encontrar la raíz del problema en un entorno LAMP (I)

Encontrar la raíz del problema en un entorno LAMP (I)

Resulta extremadamente común escuchar dos escusas muy malas cuando hay problemas en un entorno LAMP:

  • Nos atacan!!!
  • Ha habido un pico de tráfico

Ambas escusas responden a una genial frase de Homer Simpson: “La culpa es de todos menos mía”

Malditos administradores de sistemas

Malditos administradores de sistemas

Cuando hay problemas en un entorno LAMP debemos tener las herramientas preparadas para poder entender a que problema nos enfrentamos.

Primero de todo deberíamos ser capaces de ver el estado de los frontales, suponiendo que el servidor web es Apache, una muy buena herramienta es el server-status.

Para que esta herramienta sea descriptiva deberemos tener el mismo valor al MaxClients que al ServerLimit, sino nos puede dar una idea equivocada de lo que ocurre en el servidor web.

Algunos casos típicos:

  • Lleno de W: Normalmente en este caso deberíamos ver la base de datos, ya que seguramente el problema esta allí. En el log del Apache aparecerá la siguiente línea si se llena del todo:
    [Wed Apr 28 03:58:33 2010] [error] server reached MaxClients setting, consider raising the MaxClients setting
    

    Por otro lado, también podría ser que el PHP que se queda colgado en algún punto, aunque es menos común.

  • Lleno de K: Es muy típico cuando un servidor web configurado “por defecto” empieza a tener cárga se acabe muriendo por tener un KeepAlive demasiado alto. Por defecto el apache lo deja a 5 segundos, lo cual en general, es demasiado alto. Se puede experimentar el valor óptimo según la aplicación, pero se puede bajar a 1 o 2 segundos sin problema.

También pueden venir problemas por el consumo abusivo de memoria RAM. El concepto abusivo puede ser muy relativo, pero por citar un ejemplo, abusivo es que la página principal de un site consuma 100MB de memoria por página servida. Para ver el consumo se puede usar indistintamente el top o el ps.

Para el caso del top podemos ordenar los procesos por su consumo de memoria con la tecla F seguida de la n (columna RES):

top ordenando los procesos por consumo de memoria

top ordenando los procesos por consumo de memoria

En el caso del ps, deberemos mirar la columna RSS. Haciendo un ps aux podemos ordenar por la columna RSS mediante un sort, por ejemplo:

# ps aux | sort -nk 6 
(...)
apache     398  0.5  0.6 306932 27764 ?        S    09:18   0:01 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache     455  0.8  0.6 306816 28184 ?        S    09:18   0:02 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache     781  1.2  0.7 307460 28308 ?        S    09:20   0:02 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache     820  0.4  0.7 255288 28456 ?        S    09:20   0:00 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache   32262  0.5  0.7 307684 28764 ?        S    09:15   0:02 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache     830  0.7  0.7 310424 29568 ?        S    09:20   0:01 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache     835  0.4  0.7 310420 30060 ?        S    09:20   0:00 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache     851  0.7  0.7 310648 31572 ?        S    09:20   0:01 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache   32163  0.5  0.7 309904 32088 ?        S    09:14   0:02 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf
apache   16101  0.0  1.7 299648 69844 ?        S    Apr21   0:01 /usr/local/apache22/bin/httpd -DNO_DETACH -f /usr/local/apache22/conf/httpd.conf

Para el problema de un consumo excesivo de memoria, como en la mayoría de casos, o se optimiza la aplicación o se compra más RAM/máquinas. Evidentemente podemos limitar la memoria deshabilitando el ini_set, pero esto provocaría que la aplicación dejase de funcionar sirviendo páginas a medias o simplemente en blanco.

Otro caso típico que he visto en aplicaciones raras (que usan curl) o que usan Lucene como motor de búsqueda es que vayan dejando un rastro de peticiones colgadas en el apache. Para ver los tiempos que tarda una petición en servirse tenemos dos opciones:

  • Añadir en los logs el tiempo que tarda a completarse una petición mediante LogFormat, el problema es que si una petición no llega a completarse no se llega a escribir en los logs nunca, por lo que si no termina no la veremos reflejada.
  • Mirar en el server-status la columna M y la SS. Las peticiones que estan en ejecución tendrán el estado W y en la columna SS los segundos desde el inicio de la petición. Se pueden ignorar las peticiones con el SS alto si el estado no es W. Un caso especial es el K, ya que nos puede ayudar a ajustar el valor óptimo de KeepAlive ajustando el número de slots ocupados con el porcentaje aceptable respecto al total que creamos oportuno

En el caso de un entorno compartido se deberían cruzar los datos del ps con los del server-status para poder ver cual de los VirtualHost esta consumiendo tantos recursos.

Otro punto importante es el número de slots (MaxClients/ServerLimit): no por más es mejor. Si tenemos una aplicación con un consumo excesivo de RAM y que encima a veces se bloquee es la combinación perfecta para dejar frito un servidor web si se añaden demasiados slots: Si cada apache consume las 100MB que decíamos anteriormente y la base de datos se bloquea (por ejemplo un ALTER TABLE de una tabla grande) cada petición se va a quedar colgada. Si a esto le sumamos un tráfico alto se van a ir acumulando hasta empezar a swapear o incluso llegar a pasar por el out-of-memory-killer. Por este motivo, en este caso, como menos slots mejor. Lo ideal es calcular el promedio de memoria por petición y conseguir que quepan en la RAM disponible. Las peticiones se irán encolando hasta llegar al valor ListenBackLog (por defecto 511) y a partir de allí daran el feo “Connection refused

He expuesto algunos casos típicos, pero evidentemente no se puede generalizar: Siempre se debe analizar bien el problema antes de empezar a cambiar valores de la configuración.

Otro día veremos como analizar una base de datos MySQL para detectar problemas típicos.

4 comments to “Encontrar la raíz del problema en un entorno LAMP (I)”

  1. También tengo en una sesión de screen corriendo apachetop que es el Top de apache, la “pega” es que sólo va mostrando el log del sitio (todos | -f logfile)

    Saludos.

  2. Muchas gracias por compartir tus conocimientos y experiencia.

    En estos días estoy “sufriendo” porque uno de los servidores se queda “frito” y no encuentro el motivo, no es por tráfico ni por consumo de recursos, porque hay varios días seguidos en que tengo mucho tráfico y no pasa nada, y de repente, cuando aparentemente todo está en calma el servidor se cuelga.

    Esperaré impacientemente las siguientes entregas 🙂

  3. Ansioso estoy por ver la continuación de este artículo. Venga… no nos hagas sufrir más 😉

    Un saludo.

  4. Dicen que lo bueno se hace esperar 😉 Estas cosas se tienen que hacer con calma, prometo no tardar demasiado

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>