Ubuntu a une configuration de tâche cron qui recherche et supprime les anciennes sessions PHP:
# 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
Mon problème est que ce processus prend très longtemps à s'exécuter, avec beaucoup d'E / S de disque. Voici mon graphique d'utilisation du processeur:
Le nettoyage en cours d'exécution est représenté par les pointes sarcelles. Au début de la période, les travaux de nettoyage de PHP étaient programmés aux heures par défaut de 09 et 39 minutes. À 15h00, j'ai supprimé le temps de 39 minutes de cron, donc un travail de nettoyage deux fois plus grand s'exécute deux fois plus souvent (vous pouvez voir les pics devenir deux fois plus larges et deux fois plus fréquents).
Voici les graphiques correspondants pour le temps d'E / S:
Et opérations sur disque:
Au pic où il y avait environ 14000 sessions actives, le nettoyage peut être exécuté pendant 25 minutes complètes, utilisant apparemment 100% d'un cœur du CPU et ce qui semble être 100% des E / S du disque pour toute la période. Pourquoi est-il si gourmand en ressources? Un ls
répertoire de session ne /var/lib/php5
prend qu'une fraction de seconde. Alors, pourquoi faut-il 25 minutes pour couper les anciennes sessions? Puis-je faire quelque chose pour accélérer cela?
Le système de fichiers de cet appareil est actuellement ext4 et fonctionne sur Ubuntu Precise 12.04 64 bits.
EDIT: je soupçonne que la charge est due au processus inhabituel "fuser" (car je m'attends à ce qu'un simple rm
soit un sacrément plus rapide que les performances que je vois). Je vais supprimer l'utilisation de l'unité de fusion et voir ce qui se passe.
la source
Réponses:
La suppression de
fuser
devrait aider. Ce travail exécute unefuser
commande (vérifiez si un fichier est actuellement ouvert) pour chaque fichier de session trouvé , ce qui peut facilement prendre plusieurs minutes sur un système occupé avec 14 000 sessions. C'était un bogue Debian (Ubuntu est basé sur Debian).Au lieu de memcached, vous pouvez également essayer d'utiliser tmpfs (un système de fichiers en mémoire) pour les fichiers de session. Comme memcached, cela invaliderait les sessions au redémarrage (cela peut être contourné en sauvegardant ce répertoire quelque part dans le script d'arrêt et en restaurant dans le script de démarrage), mais sera beaucoup plus facile à configurer. Mais cela ne résoudra pas le
fuser
problème.la source
fuser
processus dans un état zombie consommant de la mémoire, ce qui entraîne un crash du serveur. Je pense que cela a déjà été corrigé dans la version de psmisc que j'utilise.fuser
processus, qui doivent tous rechercher l'ensemble/proc/
des fichiers ouverts.Félicitations d'avoir un site Web populaire et d'avoir réussi à le faire fonctionner sur une machine virtuelle pendant tout ce temps.
Si vous enregistrez vraiment deux millions de pages vues par jour, alors vous allez empiler BEAUCOUP de sessions PHP dans le système de fichiers, et elles vont prendre beaucoup de temps à supprimer, que vous utilisiez
fuser
ourm
ou aspirateur.À ce stade, je vous recommande de rechercher d'autres moyens de stocker vos sessions:
memcached
. C'est rapide comme l'éclair, mais si le serveur plante ou redémarre, toutes vos sessions sont perdues et tout le monde est déconnecté.la source
rm
.Ainsi, les options de stockage de session Memcached et de base de données suggérées par les utilisateurs ici sont à la fois de bons choix pour augmenter les performances, chacune avec ses propres avantages et inconvénients.
Mais en testant les performances, j'ai constaté que le coût énorme des performances de cette maintenance de session est presque entièrement dû à l'appel à
fuser
la tâche cron. Voici les graphiques de performances après le retour au travail cron Natty / Oneiric qui utiliserm
au lieu defuser
couper les anciennes sessions, le basculement se produit à 2h30.Vous pouvez voir que la dégradation périodique des performances provoquée par le nettoyage de session PHP d'Ubuntu est presque entièrement supprimée. Les pics montrés dans le graphique des opérations sur disque sont maintenant beaucoup plus petits en amplitude, et à peu près aussi maigres que ce graphique peut éventuellement mesurer, montrant une petite interruption courte où les performances du serveur étaient auparavant considérablement dégradées pendant 25 minutes. L'utilisation supplémentaire du processeur est entièrement éliminée, il s'agit désormais d'un travail lié aux E / S.
(un travail d'E / S non lié s'exécute à 05h00 et le travail du processeur s'exécute à 7h40, ce qui provoque leurs propres pics sur ces graphiques)
Le travail cron modifié que j'exécute actuellement est le suivant:
la source
-print0 | xargs ...
n'est pas nécessaire - vous pouvez simplement partir de-delete
là. Mais cela fonctionnera dans les deux sens avec une vitesse comparable.Je suis tombé sur ce post en faisant des recherches sur les sessions. Bien que la réponse acceptée soit très bonne (et l'appel de l'unité de fusion a été supprimé du script gc depuis un certain temps), je pense qu'il vaut la peine de noter quelques autres considérations si quelqu'un d'autre rencontre un problème similaire.
Dans le scénario décrit, l'OP utilisait ext4. Les répertoires dans les fichiers de stockage ext4 stockent dans un format de base de données htree - ce qui signifie qu'il y a un impact négligeable dans la conservation de nombreux fichiers dans un seul répertoire par rapport à leur distribution dans plusieurs répertoires. Ce n'est pas le cas de tous les systèmes de fichiers. Le gestionnaire par défaut en PHP vous permet d'utiliser plusieurs sous-répertoires pour les fichiers de session (mais notez que vous devez vérifier que le processus de contrôle se reproduit dans ces répertoires - le travail cron ci-dessus ne le fait pas).
Une grande partie du coût de l'opération (après la suppression de l'appel à l'unité de fusion) provient de la recherche de fichiers qui ne sont pas encore périmés. L'utilisation (par exemple) d'un seul niveau de sous-répertoires et de 16 tâches cron à la recherche dans chaque sous-répertoire (0 /, 1 /, ... d /, e /, f /) atténuera les charges générées.
L'utilisation d'un gestionnaire de session personnalisé avec un substrat plus rapide vous aidera - mais il y a beaucoup de choix (memcache, redis, socket de gestionnaire mysql ...) en laissant de côté la plage de qualité de ceux publiés sur Internet, que vous choisissez dépend de l'exact exigences concernant votre application, votre infrastructure et vos compétences, sans oublier qu'il existe fréquemment des différences dans la gestion de la sémantique (notamment le verrouillage) par rapport au gestionnaire par défaut.
la source
Avec ce type de trafic, vous ne devriez pas mettre de sessions sur un disque. Vous devriez utiliser quelque chose comme memcache. Tout ce que vous avez à faire est de configurer php et aucun changement de code ne sera nécessaire. Voir par exemple
http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/
La raison pour laquelle cela prend si longtemps est due à la quantité énorme de fichiers qu'il doit trier pour voir lesquels peuvent être supprimés. Memcache peut expirer automatiquement ces derniers en fonction de la durée de votre session que vous avez définie dans votre code.
la source