Wie kann ich die Ursache eines offensichtlichen Speicherverlusts in meiner Apache / PHP-basierten Web-App ermitteln?

18

Ungefähr einmal in der Woche, aber manchmal sogar ein paar Mal am Tag, nachdem meine EC2-Instanzen tagelang fehlerfrei gelaufen sind, reagieren sie nicht mehr. Munins Speichergraphen erzählen eine recht einfache Geschichte: Der den "Apps" zugewiesene Speicher wächst und hört erst auf, wenn der Swap vollständig genutzt und die Instanz effektiv auf die Knie gesenkt wird. Ein anderes benutzerdefiniertes Diagramm zeigt, dass der ständig wachsende Prozess Apache2 ist.

Ich führe ein Standard-Prefork-Apache-Setup mit mod_php und einigen PHP-Skripten aus. Wie Sie in der folgenden Grafik sehen können, geschieht etwas, das Apache2-Prozesse dazu veranlasst, immer mehr Speicher zu verbrauchen. Die erste grüne Spitze, die ich rechtzeitig abfing und Apache neu startete, bevor die Dinge außer Kontrolle gerieten. Der zweite Spike wurde etwas weiter und die Instanz musste sofort neu gestartet werden.

Munin Memory Graph

Ich frage mich, wie ich das am besten debuggen kann. Was ist ein guter Weg, um herauszufinden, ob es sich um Apache oder eine Kombination aus PHP und meinem Code handelt, der die übermäßige Speichernutzung verursacht, ohne PHP mit FastCGI einzurichten und in seinen eigenen Prozessen zum Laufen zu bringen? Welche Schritte würdet ihr unternehmen, um dieses Problem aufzuspüren?


UPDATE: Ich war in der Lage, das Leck aufzuspüren, nachdem ich mich gestrafft hatte, wie Matt unten vorgeschlagen hat.

Nachdem ich einen Apache2-Prozess gefunden hatte, der allmählich und kontinuierlich im Speicher wuchs, fügte ich meinem PHP-Skript ein paar weitere error_log () -Aufrufe hinzu, die die Gesamtmenge an RSS ausdruckten, die zu verschiedenen Zeitpunkten in seiner Ausführung verwendet wurde (unter Verwendung der Ausgabe von ps). Das stellte sich jedoch als irreführend heraus - während es den Anschein hatte, dass RSS erst sprang, nachdem mein Skript ausgeführt worden war, ergab ein späteres Debuggen, dass dies in der Tat nicht der Fall war. Achtung!

Glücklicherweise haben sich all diese error_log () -Aufrufe am Ende als nützlich erwiesen. Als ich strace ( strace -p <pid> -tt -o trace.log -s 256) startete, stellte ich fest, dass der Prozess für jede Anforderung rund 400 KB Arbeitsspeicher reservierte (suchen Sie nach dem Systemaufruf 'brk' und subtrahieren Sie den Parameter des ersten Aufrufs vom Parameter des letzten Aufrufs - einige kommen normalerweise in einem Nacheinander). Ich suchte dann nach dem letzten "Write" -Systemaufruf, der meine error_log () -Meldung enthielt, die mir mitteilte, an welcher Stelle im Skript der Speicher zugewiesen wurde. Mit ein paar strategisch platzierten Aufrufen von error_log (), um die Position genauer zu bestimmen, habe ich endlich den Schuldigen gefunden.

Der Speicher leckte, als wir curl_exec () in unserem PHP-Skript aufriefen. Ein Curl-Code im Zusammenhang mit der Verarbeitung einer SSL-Verbindung hat etwas falsch gemacht - das Leck ist verschwunden, als ich auf HTTP umgestiegen bin. Das Änderungsprotokoll von Curl verweist auf einige SSL-Speicherverluste, die in 7.19.5 behoben wurden (wir waren in 7.18.2). Daher werde ich das als Nächstes versuchen.

In der Zwischenzeit arbeite ich mit einem sehr niedrigen Wert für MaxRequestsPerChild, der Apache in einem vernünftigen Rahmen hält. Vielen Dank an alle!

Ondrej
quelle
Wie variiert die Anzahl der untergeordneten Apache-Prozesse im selben Zeitraum?
SimonJ
@ SimonJ Simon, tolle Frage, die Zahl bleibt ziemlich gleich, plus minus ein paar Prozesse. Sie beträgt ungefähr 60, wenn die Server Probleme haben oder sich im Ruhezustand befinden. Ich werde einen Munin-Graphen erstellen, um 100% sicher zu sein.
Donnerstag,
Keine Lösung, aber wenn eine der Anwendungen dafür bekannt ist, dass sie wie verrückt nach RAM frisst, ist es besser, den Swap auszuschalten: Wenn der Kernel einen Mangel an RAM feststellt, werden die größten Speicherfresser (Apache) getötet. Wenn Swap aktiviert ist, bricht der Kernel einige Prozesse viel später ab, da Swap viel langsamer ist als RAM. Kein Swap - schnellere Wiederherstellung, geringere Ausfallzeiten. (Ich habe nur versucht, Swap in einem ähnlichen Fall auf einem Computer mit 8 GB RAM zu deaktivieren, also YMMW.)
Chronos

Antworten:

5

Auf der Suche nach dem, was das Problem verursacht, kann ein Schmerz im Arsch sein. Das erste, was ich tun würde, wenn ich MaxRequestsPerChildein solches Problem hätte, ist, es auf einen aggressiv niedrigen Wert (~ 100-200) zu reduzieren und zu prüfen, ob dies einen Unterschied macht. Wenn dies der Fall ist, haben Sie wahrscheinlich Code, der irgendwo Speicher in einer Schleife verliert, und Sie möchten ein Code-Audit durchführen.

Eine andere Sache, die Sie sich ansehen sollten, ist der vollständige Status von Apache. Prüfen Sie, ob Sie herausfinden können, welche bestimmte Anforderung den Speicherverlust verursacht. Ermitteln Sie die PIDs für Ihre verdächtigen Prozesse und führen Sie eine Analyse durch.

matt
quelle
Vielen Dank, Matt. 'ps aux | grep apache2 'sagt mir, dass von den rund 60 aktiven Prozessen rund ein Dutzend viel mehr Speicher beanspruchen als sie sollten (> 100 MB in RSS). Ich habe mir die Ausgabe von / proc / <pid> / smaps angesehen und festgestellt, dass jede genau eine anonyme Zuordnung hat, die über 95% des Speicherplatzes einnimmt. Ich versuche jetzt herauszufinden, was und wann dieser riesige Speicherblock zugewiesen wurde. Ich werde nachsehen - danke für den Tipp.
Donnerstag,
2

Freitag um genau 23 Uhr? Entspricht das einer Backup-Zeit? Verfügt Ihr System zu diesem Zeitpunkt über die E / A, um Prozesse und Sicherungen zu bedienen? Trending Software auch Trend # procs oder sogar Apache Scoreboard, wie wäre es mit Disk I / O?

Das erste, was ich tun würde, wäre, zu berechnen, wie viel Mem jeder Proc benötigt, und dann ein angemessenes Limit für MaxRequests in Apache festzulegen, sodass $ procmem * $ procs den verfügbaren RAM nicht überschreiten kann. Ich vermute, dass Ihre Instanz neu gestartet werden muss, da OOM eine Hexenjagd startet, die wahrscheinlich (oft) nicht sehr fruchtbar ist. Sie müssen sicherstellen, dass Ihre Box diese schweren Zeiten bewältigt, indem Sie innerhalb ihrer Grenzen bleiben und nicht tauschen und schon gar nicht OOM. Dies ist schwieriger, wenn Cronjobs ausgeführt werden, und äußerst schwierig, wenn die Cronjobs einseitig ausgeführt werden, ohne sicherzustellen, dass sie sicher ausgeführt werden können (dh das Skript prüft nicht alle 5 Minuten, ob die letzten 5 Minuten noch ausgeführt werden).

Jetzt, da Sie sichergestellt haben, dass Sie Ihre Box auch dann nicht neu starten müssen, wenn etwas schief läuft, läuft es für Sie viel besser. In diesen schwierigen Zeiten können Sie sich anmelden und sich einen guten Überblick über die Vorgänge mit top, dstat, free -m, iostat usw. verschaffen.

Die Methode von Matt ist vielleicht einen Versuch wert, sollte aber nur als Tool zur Fehlerbehebung verwendet werden. Ich empfehle nicht, sie so beizubehalten, da das Gesamtproblem dadurch viel schwerer zu finden ist, wenn Sie das nächste Mal danach suchen. Das heißt, es werden nur Probleme mit Apache / Modulen und nichts in Ihrem Code wirklich herausgeputzt. Ich denke, Sie stimmen zu, dass die Chancen gut stehen, dass es sich nicht um eine Art Speicherverlust im Apache-Modul handelt (vorausgesetzt, Sie verwenden eine seriöse Distribution).

fimbulvetr
quelle
0

Die erste Frage ist, welche Anwendung über Apache ausgeführt wird.

Ist es eine, die Sie geschrieben haben, oder eine Drittanbieter-App?

Auf welche anderen Komponenten / Pakete wird verwiesen?

Sind Sie über Ihre Pakete auf dem Laufenden?

Gibt es in Ihren httpd.confDateien etwas Bestimmtes in Bezug auf die Leistung?

Labyrinth
quelle
0

Wenn Ihr Problem durch die PHP-Anwendung verursacht wird und Sie die Software selbst geschrieben haben, empfehle ich Ihnen, einen Profiler wie z . B. PHP Quick Profiler zu verwenden . Wenn Sie viele Datenbanktransaktionen durchführen, kann Ihnen eine Software wie zB Kontrollbase dabei helfen, das Problem dort zu finden.

Raffael Luthiger
quelle
Raffael, danke. Ja, die PHP-App gehört mir und trifft keine SQL-Datenbanken. Ich gebe PHP Quick Profiler eine Chance und erstatte Bericht.
Donnerstag,