Environ une fois par semaine, mais parfois même quelques fois par jour après un bon fonctionnement pendant des jours, mes instances EC2 ne répondent plus. Les graphiques de la mémoire de Munin racontent une histoire assez simple: la mémoire allouée aux "applications" commence à croître et ne s'arrête pas jusqu'à ce que le swap soit pleinement utilisé et que l'instance soit effectivement mise à genoux. Un autre graphique personnalisé montre que le processus en croissance constante est apache2.
J'exécute une configuration Apache standard préfork avec mod_php et quelques scripts PHP. Comme vous pouvez le voir dans le graphique ci-dessous, quelque chose se produit qui déclenche les processus apache2 pour commencer à consommer de plus en plus de mémoire. Le premier pic vert que j'ai attrapé à temps et a redémarré Apache avant que les choses ne deviennent incontrôlables. Le deuxième pic est allé un peu plus loin et l'instance a dû être redémarrée.
Ce que je me demande, c'est comment déboguer au mieux. À moins de configurer PHP avec FastCGI et de le faire fonctionner dans ses propres processus, quelle est une bonne façon de savoir si c'est Apache ou une combinaison de PHP et de mon code qui cause l'utilisation excessive de la mémoire? Quelles mesures prendriez-vous pour dépister ce problème?
MISE À JOUR: J'ai pu suivre la fuite après avoir impliqué Strace, comme Matt l'a suggéré ci-dessous.
Après avoir trouvé un processus apache2 qui augmentait progressivement et continuellement en mémoire, j'ai ajouté quelques appels error_log () à mon script PHP qui imprimait la quantité totale de RSS utilisée à divers moments de son exécution (en utilisant la sortie de ps). Cela s'est toutefois révélé trompeur - alors qu'il semblait que RSS n'a sauté qu'après l'exécution de mon script, un débogage ultérieur a révélé que ce n'était pas le cas. Faites attention!
Heureusement, tous ces appels error_log () se sont avérés utiles à la fin. Lorsque j'ai lancé strace ( strace -p <pid> -tt -o trace.log -s 256
), j'ai vu que pour chaque demande, le processus allouait environ 400 Ko de mémoire (recherchez l'appel système 'brk' et soustrayez le paramètre du premier appel du dernier appel - quelques-uns viennent généralement en un après un autre). J'ai ensuite recherché le dernier appel système «écriture» qui contenait mon message error_log (), qui m'a dit à quel moment du script la mémoire était allouée. Avec quelques appels error_log () placés stratégiquement pour localiser plus précisément l'emplacement, j'ai finalement trouvé le coupable.
La mémoire fuyait lorsque nous avons appelé curl_exec () à partir de notre script PHP. Certains codes curl liés à la gestion d'une connexion SSL font quelque chose de mal - la fuite a disparu lorsque je suis passé à HTTP. Le journal des modifications de Curl fait référence à quelques fuites de mémoire SSL qui ont été corrigées dans 7.19.5 (nous étions sur 7.18.2), donc je vais essayer cela ensuite.
En attendant, je cours avec un MaxRequestsPerChild très bas qui maintient Apache dans des limites raisonnables. Merci tout le monde!