Ubuntu tiene un trabajo cron configurado que busca y elimina sesiones PHP antiguas:
# Look for and purge old sessions every 30 minutes
09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] \
&& [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
-maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
fuser -s {} 2> /dev/null \; -delete
Mi problema es que este proceso está tardando mucho en ejecutarse, con mucho disco IO. Aquí está mi gráfico de uso de CPU:
La limpieza en ejecución está representada por las espigas verde azulado. Al comienzo del período, los trabajos de limpieza de PHP se programaron en los tiempos predeterminados de 09 y 39 minutos. A las 15:00, eliminé el tiempo de 39 minutos de cron, por lo que un trabajo de limpieza del doble del tamaño se ejecuta la mitad de las veces (puede ver que los picos se doblan el doble y la mitad de la frecuencia).
Aquí están los gráficos correspondientes para el tiempo IO:
Y operaciones de disco:
En el pico donde había aproximadamente 14,000 sesiones activas, se puede ver que la limpieza se ejecuta durante 25 minutos completos, aparentemente usando el 100% de un núcleo de la CPU y lo que parece ser el 100% del disco IO durante todo el período. ¿Por qué es tan intensivo en recursos? Una ls
de las sesiones del directorio /var/lib/php5
toma solo una fracción de segundo. Entonces, ¿por qué se tarda 25 minutos completos en recortar las sesiones antiguas? ¿Hay algo que pueda hacer para acelerar esto?
El sistema de archivos para este dispositivo es actualmente ext4, ejecutándose en Ubuntu Precise 12.04 de 64 bits.
EDITAR: sospecho que la carga se debe al proceso inusual "fusor" (ya que espero que un simple rm
sea mucho más rápido que el rendimiento que estoy viendo). Voy a eliminar el uso del fusor y ver qué pasa.
fuente
Respuestas:
La eliminación de
fuser
debería ayudar. Este trabajo ejecuta unfuser
comando (verifique si un archivo está abierto actualmente) para cada archivo de sesión encontrado , lo que puede tomar fácilmente varios minutos en un sistema ocupado con 14k sesiones. Este fue un error de Debian (Ubuntu se basa en Debian).En lugar de memcached, también puede intentar usar tmpfs (un sistema de archivos en memoria) para los archivos de sesión. Al igual que memcached, esto invalidaría las sesiones al reiniciar (esto se puede solucionar haciendo una copia de seguridad de este directorio en algún lugar del script de apagado y restaurando el script de inicio), pero será mucho más fácil de configurar. Pero no ayudará con el
fuser
problema.fuente
fuser
procesos en una memoria que consume estado zombie, lo que conduce a un bloqueo del servidor. Creo que eso ya se ha solucionado en la versión de psmisc que estoy usando.fuser
procesos, todos los cuales deben buscar/proc/
archivos abiertos en el conjunto .Felicitaciones por tener un sitio web popular y lograr mantenerlo funcionando en una máquina virtual durante todo este tiempo.
Si usted está realmente tirando de dos millones de páginas vistas por día, entonces usted va a apilar un montón de sesiones de PHP en el sistema de archivos, y que va a tomar mucho tiempo para eliminar independientemente de si se utiliza
fuser
orm
o una aspiradora.En este punto, te recomiendo que busques formas alternativas de almacenar tus sesiones:
memcached
. Esto es rápido como un rayo, pero si el servidor falla o se reinicia, todas sus sesiones se pierden y todos se desconectan.fuente
rm
.Por lo tanto, las opciones de almacenamiento de sesión de Memcached y de base de datos sugeridas por los usuarios aquí son buenas opciones para aumentar el rendimiento, cada una con sus propios beneficios e inconvenientes.
Pero mediante las pruebas de rendimiento, descubrí que el enorme costo de rendimiento del mantenimiento de esta sesión se debe casi por completo a la llamada
fuser
en el trabajo cron. Aquí están los gráficos de rendimiento después de volver al trabajo cron Natty / Oneiric que utiliza enrm
lugar defuser
recortar sesiones antiguas, el cambio ocurre a las 2:30.Puede ver que la degradación periódica del rendimiento causada por la limpieza de la sesión PHP de Ubuntu se elimina casi por completo. Los picos que se muestran en el gráfico de Operaciones de disco ahora son mucho más pequeños en magnitud, y casi tan delgados como este gráfico puede medir, mostrando una pequeña interrupción corta donde anteriormente el rendimiento del servidor se degradó significativamente durante 25 minutos. El uso adicional de CPU se elimina por completo, ahora es un trabajo vinculado a IO.
(un trabajo de E / S no relacionado se ejecuta a las 05:00 y el trabajo de la CPU se ejecuta a las 7:40, lo que causa sus propios picos en estos gráficos)
El trabajo cron modificado que estoy ejecutando ahora es:
fuente
-print0 | xargs ...
no es necesario, simplemente puedes irte de-delete
allí. Pero funcionará en ambos sentidos con una velocidad comparable.Me encontré con esta publicación cuando hice algunas investigaciones sobre las sesiones. Si bien la respuesta aceptada es muy buena (y la llamada del fusor se ha eliminado del script gc durante algún tiempo), creo que vale la pena señalar algunas otras consideraciones si alguien más se encuentra con un problema similar.
En el escenario descrito, el OP estaba usando ext4. Los directorios en ext4 almacenan datos de archivos en un formato de base de datos htree, lo que significa que hay un impacto insignificante en mantener muchos archivos en un solo directorio en comparación con distribuirlos en varios directorios. Esto no es cierto para todos los sistemas de archivos. El controlador predeterminado en PHP le permite usar múltiples subdirectorios para los archivos de sesión (pero tenga en cuenta que debe verificar que el proceso de control se repita en esos directorios; el trabajo cron anterior no lo hace).
Gran parte del costo de la operación (después de eliminar la llamada al fusor) surge de mirar archivos que aún no están obsoletos. El uso (por ejemplo) de un solo nivel de subdirectorios y 16 trabajos cron que buscan en cada subdirectorio (0 /, 1 /, ... d /, e /, f /) suavizarán los baches de carga que surjan.
El uso de un controlador de sesión personalizado con un sustrato más rápido ayudará, pero hay mucho para elegir (memcache, redis, mysql handler socket ...) dejando de lado el rango de calidad de los publicados en Internet, que usted elige depende de la exactitud requisitos con respecto a su aplicación, infraestructura y habilidades, sin olvidar que con frecuencia existen diferencias en el manejo de la semántica (especialmente el bloqueo) en comparación con el controlador predeterminado.
fuente
Con ese tipo de tráfico no debería poner sesiones en desuso. Deberías estar usando algo como memcache. Todo lo que tiene que hacer es configurar php y no será necesario cambiar el código. Ver por ejemplo
http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/
La razón por la que lleva tanto tiempo se debe a la gran cantidad de archivos que tiene que clasificar para ver cuáles se pueden eliminar. Memcache puede caducar automáticamente, dada la duración de la sesión que configuró en su código.
fuente