Comment enquêter sur une fuite de mémoire avec Apache et PHP?

16

Nous gérons un site Web Drupal lourd qui effectue une modélisation financière. Nous semblons rencontrer une sorte de fuite de mémoire étant donné que les heures supplémentaires utilisées par Apache augmentent alors que le nombre de processus Apache reste stable:

entrez la description de l'image ici

entrez la description de l'image ici

Nous savons que le problème de mémoire vient d'apache / PHP car chaque fois que nous émettons un problème d' /etc/init.d/httpd reloadutilisation de la mémoire (voir capture d'écran ci-dessus et sorties CLI ci-dessous):

Avant le rechargement httpd

$ gratuit
             total des tampons partagés gratuits utilisés mis en cache
Mem: 49447692 45926468 3521224 0 191100 22609728
- / + tampons / cache: 23125640 26322052
Échange: 2097144 536552 1560592

Après le rechargement httpd

$ gratuit
             total des tampons partagés gratuits utilisés mis en cache
Mem: 49447692 28905752 20541940 0 191360 22598428
- / + tampons / cache: 6115964 43331728
Échange: 2097144 536552 1560592

Chaque thread apache se voit attribuer un PHP memory_limitde 512 Mo, ce qui explique l'utilisation élevée de la mémoire, le faible volume de demandes et un délai max_execution_timede 120 secondes qui devrait terminer les threads dont l'exécution prend plus de temps, et devrait donc empêcher la croissance constante de l'utilisation de la mémoire que nous sommes. voyant.

Q: Comment pourrions-nous rechercher la cause de cette fuite de mémoire?

Idéalement, je recherche des étapes de dépannage que je peux effectuer sur le système sans avoir à déranger l'équipe de développement.

Information additionnelle:

OS: RHEL 5.6
PHP: 5.3
Drupal: 6.x
MySQL: 5.6

Pour info, nous sommes conscients du problème de permutation que nous étudions séparément et n'a rien à voir avec la fuite de mémoire que nous avons observée avant le début de la permutation.

Max
la source
La dernière fois que j'ai rencontré un grave problème d'utilisation de la mémoire avec LAMP + Drupal, c'était lorsque j'avais une bibliothèque PHP memcached en cours d'utilisation. Après l'avoir emporté, l'utilisation de la mémoire a chuté de façon spectaculaire. Juste une supposition. Pourrait taper une réponse appropriée pour vous un peu plus tard.
Janne Pikkarainen
@JannePikkarainen: nous utilisons la memcachedbibliothèque PHP . Sur la base de la page d'administration de memcache memcache.php, tout ce que nous pouvons voir, c'est que nous avons alloué 5GBà memcache, qui 3.3GBest utilisé. Ce serait formidable si vous pouviez nous aider davantage ici.
Max
Oui, le memcacheddémon lui-même est probablement très bien. C'est la bibliothèque PHP memcache qui pourrait ou non fuir la mémoire (et donc augmenter la consommation de mémoire des processus Apache). Mon problème était il y a environ 1-2 ans, donc les choses auraient pu être corrigées après cela. Quoi qu'il en soit, si memcached n'est pas obligatoire pour vous, essayez de le désactiver pendant un certain temps et voyez si l'utilisation de la mémoire Apache augmente toujours.
Janne Pikkarainen
Quel est le vrai problème? Les performances sont-elles médiocres? Vous nous dites des symptômes sans expliquer quel problème nous sommes censés vous aider à résoudre. (Et quel est ce problème d'échange dont vous parlez? Échangez-vous tellement qu'il affecte les performances?)
David Schwartz
@DavidSchwartz: le problème est que si nous ne redémarrons pas httpd, l'utilisation de la mémoire continue de croître et la boîte se bloque finalement avec certains messages de noyau de mémoire insuffisante. Les performances sont bonnes (jusqu'à ce que l'utilisation de la mémoire approche de la limite de mémoire). Veuillez ignorer le problème de permutation.
Max

Réponses:

11

Nous savons que le problème de mémoire vient d'apache / PHP car chaque fois que nous émettons un /etc/init.d/httpd recharger les baisses d'utilisation de la mémoire

Non - cela signifie simplement que cela est lié au trafic Web. Vous avez poursuivi en mentionnant que vous exécutez mysql sur la boîte - probablement en gérant les données pour le serveur Web - cela pourrait tout aussi bien être le coupable ici. De même que d'autres services que votre webstack utilise et que vous n'avez pas mentionnés.

Chaque thread apache se voit attribuer une limite de mémoire PHP de 512 Mo, ce qui explique

Non, ce n'est pas le cas. Vous signalez une moyenne de 7 et un maximum de 25 serveurs occupés - mais votre graphique de mémoire montre un delta d'environ 25 Go.

Vraiment, vous devriez recommencer avec un réglage HTTP de base - vous semblez exécuter un 256 httpds constant, mais votre utilisation maximale est de 25 - c'est tout simplement stupide.

et un max_execution_time de 120 sec qui devrait terminer les threads dont l'exécution prend plus de temps

Non - seulement si le thread d'exécution est dans l'interpréteur PHP - pas si PHP est bloqué.

qui effectue la modélisation financière

(soupir)

Il aurait été utile de fournir des détails sur la façon dont vous avez configuré Apache, threaded ou prefork, quelle version, comment PHP est appelé (module, cgi, fastcgi), si vous utilisez des connexions persistantes, si vous utilisez des procédures stockées.

Je vous suggère de commencer par déplacer mysql sur une machine séparée et d'arrêter d'utiliser des connexions persistantes (si vous les utilisez actuellement). Définissez la limite de mémoire beaucoup plus bas et remplacez-la sur une base par script. Assurez-vous que le récupérateur de déchets de référence circulaire est installé et configuré.

symcbean
la source
2

Vous avez probablement résolu votre problème maintenant. Par intérim pour empêcher le serveur de swapping / thrashing, j'exécute la commande suivante toutes les heures à partir de cron:

#!/bin/sh 
sync; echo 3 > /proc/sys/vm/drop_caches

Je ne dis pas que c'est une solution, juste un moyen de faire fonctionner les choses et de minimiser les temps morts lorsque vous étudiez la cause réelle de la fuite de mémoire.

Plus de détails ici.

http://www.tecmint.com/clear-ram-memory-cache-buffer-and-swap-space-on-linux/

patrick
la source
1

Apparemment, c'est ainsi que PHP fonctionne - et si vous faites de longues boucles où vous allouez des objets et qui sait si vous les passez également via une référence, la seule façon de le gérer est donc après N requêtes pour chaque processus PHP pour l'arrêter. Si vous exécutez PHP en tant que CGI, chaque demande le fait réapparaître - donc pas de fuite de mémoire, et la baisse des performances n'est peut-être pas si importante. Vous pouvez également exécuter fast-cgi, où, par exemple, chaque 1000 requêtes le processus php-fcgi est tué et sa mémoire libérée - encore une fois aucune fuite de mémoire. Si vous exécutez PHP en tant que module mod_php, vous pouvez essayer de configurer maxrequests dans httpd.conf pour voir si cela aide. J'essaierais de configurer par exemple 10 - si cela fonctionne, la baisse des performances ne sera pas élevée, mais il ne devrait y avoir aucune fuite de mémoire,

Andrew Smith
la source
-1

Vérifiez la mémoire dans le fichier global php.ini. ne décalez pas simplement la valeur comme 1 G, etc ... Je recommanderais fortement qu'un php.ini local soit introduit dans ce compte afin de ne pas affecter le serveur entier. Je recommanderais de définir la limite globale de php.ini à environ 64 Mo, car cela est généralement suffisant pour la plupart des comptes

vérifiez également vos paramètres apache

Nikhil Babu
la source