Apache erreicht MaxClients und sperrt den Server

9

Ich habe derzeit einen Apache2-Server mit mpm-preforkund mod_phpauf einem OpenVZ-VPS mit 512 MB realem / 1024 MB Burstable RAM (kein Swap). Nachdem ich einige Tests ausgeführt hatte, stellte ich fest, dass die maximale Prozessgröße, die Apache erhält, 23 MaxClientsMB beträgt. Daher habe ich 25 festgelegt (23 MB x 25 = 575 MB, für mich in Ordnung). Ich beschloss, einige Auslastungstests auf meinem Server durchzuführen, und die Ergebnisse ließen mich verwirrt.

Ich verwende abauf meinem Desktop-Computer die Anforderung der Hauptseite von einem WordPress-Blog.

Wenn ich abmit 24 gleichzeitigen Verbindungen arbeite, scheint alles in Ordnung zu sein. Sicher, die CPU steigt, der freie Arbeitsspeicher sinkt und das Ergebnis ist eine Antwortzeit von ca. 2-3 Sekunden pro Anforderung.

Wenn ich jedoch abmit 25 gleichzeitigen Verbindungen (meinem Serverlimit) arbeite, bleibt Apache nach ein paar Sekunden hängen. Es beginnt mit der Verarbeitung der Anforderungen, reagiert dann nicht mehr, die CPU kehrt zu 100% in den Leerlauf zurück und abläuft ab. Das Apache-Protokoll gibt an, dass es erreicht wurde MaxClients.

In diesem Fall hält sich Apache mit 25 laufenden Prozessen auf dem Laufenden (sie sind alle in "W", wenn ich den Serverstatus überprüfe) und erst nach der TimeOutEinstellung beginnen die Prozesse zu sterben und der Server reagiert erneut (in meinem Fall ist er festgelegt bis 45).

Meine Frage: Ist das erwartetes Verhalten? Warum stirbt Apache nur, wenn es erreicht MaxClients? Wenn es mit 24 Verbindungen funktioniert, sollte es nicht mit 25 funktionieren. Nehmen Sie sich vielleicht mehr Zeit, um auf jede Anfrage zu antworten und den Rest in die Warteschlange zu stellen.

Es klingt für mich etwas seltsam, dass jedes laufende Kind abeinen Webserver alleine töten kann, indem es die gleichzeitigen Verbindungen zu den Servern herstellt MaxClients.

Rodrigo Sieiro
quelle

Antworten:

17

HA! Ich habe das Problem endlich selbst gefunden. Es hängt mehr mit der Programmierung als mit dem Serveradministrator zusammen, aber ich habe mich trotzdem entschlossen, die Antwort hier zu platzieren, da ich bei der Suche in Google festgestellt habe, dass ich nicht der einzige bin, der solche Probleme hat (und da Apache hängt, ist die erste Vermutung, dass es ein Problem gibt mit dem Server).

Das Problem liegt nicht bei Apache, sondern bei meinem Wordpress. Genauer gesagt mit meinem Thema. Ich verwende ein Thema namens Lightworld und es unterstützt das Hinzufügen eines Bildes zum Blog-Header. Um dies zu ermöglichen, wird die Bildgröße mithilfe der PHP-Funktion überprüft getimagesize(). Da diese Funktion eine weitere http-Verbindung zum Server öffnete, um das Image abzurufen, erstellte jede Anforderung von abeine weitere interne Anforderung von PHP. Da ich alle auf meinem Server verfügbaren Slots verwendet habe, wurden diese PHP-Anforderungen in die Warteschlange gestellt, aber Apache konnte sie nie erreichen, da alle Prozesse mit der ursprünglichen Anforderung gesperrt waren, die darauf wartete, dass ein Slot die interne PHP-Anforderung abschließt.

Grundsätzlich versetzte PHP meinen Server in einen Deadlock-Zustand, und Apache funktionierte erst normal, nachdem diese Verbindungen abgelaufen waren und auf ihre "untergeordnete" Anfrage gewartet hatten.

Nachdem ich diese Funktion aus meinem Design entfernt habe, kann abich jetzt meinen Server mit so vielen gleichzeitigen Verbindungen wie ich möchte, und Apache stellt sie wie erwartet in die Warteschlange.

Rodrigo Sieiro
quelle
Vielen Dank, dass Sie dies hier veröffentlicht haben. Ich habe seit einigen Tagen versucht, ein Problem mit genau den gleichen Symptomen herauszufinden - denken Sie, wir haben auch einen Deadlock!
James Yale
Wie haben Sie das festgestellt? Ich bin hauptsächlich an den Protokollen und Tools interessiert, mit denen Sie die sekundäre ausgehende Anforderung ermittelt haben.
Anirudh Goel
2

Was hier passiert, ist, dass Sie 25 Threads haben, die Verbindungen akzeptieren können, und Sie senden 26 gleichzeitige Anfragen. Diese letzte Anforderung befindet sich in der Socket-Warteschlange, abhängig von der Größe Ihres Backlogs.

Das zweite Problem ist, dass alles, was Sie ausführen, was 2-3 Sekunden dauert, lange genug dauert, um zu reagieren, dass die 25 gleichzeitigen Verbindungen es verlangsamen. sleep (1) funktioniert möglicherweise, aber wenn Sie eine Dateisperre oder eine Tabellensperre über MySQL ausführen, wartet jede parallele Anforderung möglicherweise auf den vorherigen Zeitpunkt, bis sie das 45-Sekunden-Timeout erreicht hat.

23 MB klingen für einen Apache-Prozess mit mod_php und allen geladenen Modulen klein. Ich vermute also, dass diese Apache-Prozesse möglicherweise etwas mehr RAM benötigen, während Ihre Anwendung ausgeführt wird. Mit MaxClients und so einem Speicher kann man nicht wirklich rechnen ... es wird etwas eng, aber man weiß es nie.

www-data  1495  0.1  0.9  56288 19996 ?        S    15:48   0:01 /usr/sbin/apache2 -k start
www-data  1500  0.0  0.5  49684 12436 ?        D    15:48   0:00 /usr/sbin/apache2 -k start

Es gibt eine Maschine, 56M- und 49M-Prozesse.

eine andere Maschine:

www-data  7767  0.1  0.1 213732 14840 ?        S    14:55   0:08 /usr/sbin/apache2 -k start
www-data  8020  0.2  0.1 212424 13660 ?        S    14:57   0:08 /usr/sbin/apache2 -k start

eine andere Maschine:

www-data 28509  0.8  0.1 161720 10068 ?        S    14:39   0:43 /usr/sbin/apache2 -k start
www-data 28511  0.8  0.1 161932 10344 ?        S    14:39   0:43 /usr/sbin/apache2 -k start

Die Speichernutzung hängt also stark von der Aufgabe ab, welche Module geladen werden usw. Bei den letzten beiden glaube ich, dass wir pdo & pdo_mysql deaktiviert haben, da diese Anwendung sie nicht verwendet.

Die eigentliche Frage ist, was machst du, das dauert 3 Sekunden? In der heutigen Welt ist dies eine Ewigkeit und wird als "blockierende" Anwendung angesehen. Apache stirbt normalerweise nicht, belässt diese Threads jedoch in der Backlog-Warteschlange, bis sie bedient werden können oder die Wartezeit abgelaufen ist. Ich glaube, Ihre Anwendung führt wahrscheinlich zu einer Zeitüberschreitung bei Apache. Probieren Sie es auf einer Seite aus, die nur phpinfo () enthält. und sehen Sie, ob die Ergebnisse gleich sind.


quelle
Danke für alle Tipps! Ich bin mir bewusst, dass ich noch viele Dinge optimieren muss (ich habe erst vor ein paar Tagen mit der Konfiguration des Servers begonnen und es ist meine erste Erfahrung mit einem VPS), aber das Problem war tiefer als das ... Ich habe eine Antwort auf die Frage, was das Problem in meinem speziellen Fall war.
Rodrigo Sieiro