Apache: Alta carga de CPU
Llevo desde el fin de semana con la mosca detrás de la oreja. Uno de los servidores que administro ha visto incrementada de forma inexperada su carga media de CPU sin motivo aparente. Donde el load average normal de 1 minuto variaba entre 0.40 y 0.80 de repente suponía cargas tan elevadas como 60 o 100 unidades.
En esos momentos puntuales que llegaban a dejar la máquina zombie el proceso que abarcaba un consumo de entre el 60% y el 90% de CPU era apache2. Intrigante que ni error.log ni slow-queries.log de MySQL (lo que normalmente suele ser cuello de botella) dieran ninguna pista.
Analytics tampoco decía nada de un aumento considerable de visitas -más bien al contrario- y el resto de herramientas de monitorización parecían cómplices del problema (¡tener tools para ésto!).
En un alarde de desesperación y viendo más o menos por dónde podían venir los tiros -a través del método de prueba y error- localicé el VirtualHost que estaba dando problemas, un código no auditado y afamado por su ausente optimización. Vamos que ya tenía precedentes, aunque ninguno de esta índole.
Después de desactivar distintas partes del dominio en más pruebas esperando focalizar el error en algún script concreto, la conclusión es que tenía que ser algo que se incluía en todos los archivos, algo común a toda la web. Así que miramos los includes comunes (si, PHP) y llegamos a la conclusión de que era problema de sesiones, sin exculpar al programador.
Una de las primeras acciones de todos los scripts es definir el tiempo de sesión a 3 días, definir el directorio donde se guardarán los archivos de sesión y arrancar la sesión. Probablemente el programador no esperaba tener 60k visitas y más de 200k páginas vistas en los 3 días que dura cada sesión, pero está claro que para apache2 suponía un problema el acceso de lectura/escritura a un mismo directorio con más de 90k archivos.
La solución inicial -a falta de más tiempo para cambiar el sistema de sesiones a memcache, Redis o cualquier otra solución basada en RAM- era sencilla, reducir el tiempo de sesión, vaciar el directorio donde se guardan las sesiones, comprobar de nuevo el load average durante un intervalo representativo y una tarea programada que monitorice el contenido de ese directorio. Después de todo la carga se ha vuelto a estabilizar entre 0.30 y 0.40.
No sé si estoy para moralejas porque la solución es temporal, pero como lo prometido es deuda me gustaría terminar esta anotación advirtiendo a todo el mundo sobre la fiabilidad del código no auditado, el uso moderado de las sesiones y las endorfinas que libera uno cuando consigue resolver algo "así".