it-swarm.com.de

PHP5-FPM verbraucht nach dem Zufall eine Menge CPU

Ich bin auf ein wirklich seltsames Problem gestoßen, bei dem ich nicht sicher bin, wie ich weiter debuggen kann. Ich habe eine NGINX + PHP5-FPM + APC-Amazon-Ubuntu-Instanz, auf der eine Website installiert ist, die ein komplexes PHP-Framework ist. Beim Versuch, das Problem zu debuggen, habe ich den Fluss darauf reduziert: Viele große Klassen werden eingeschlossen, Hauptobjekte werden erstellt, Sitzung wird gestartet, Array von Konfigurationen wird aus memcached abgerufen, eine XML-Datei wird aus memcached, HTML abgerufen Vorlagen sind enthalten, die Ausgabe wird an den Client gesendet.

Dann benutze ich das http_load-Tool, um die Website mit 20 Anfragen pro Sekunde zu belasten: http_load -timeout 10 -rate 20 -fetches 10000 ./urls.txt

Was als nächstes passiert, ist ziemlich seltsam. top zeigt eine Reihe von php5-fpm-Prozessen, die jeweils einige Prozent der CPU beanspruchen, und alles läuft reibungslos wie folgt:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28440 www-data 20 0 67352 10m 5372 S 4.3 1.8 0:20.33 php5-fpm
28431 www-data 20 0 67608 10m 5304 S 3.3 1.8 0:16.77 php5-fpm
28444 www-data 20 0 67352 10m 5372 S 3.3 1.8 0:17.17 php5-fpm
28445 www-data 20 0 67352 10m 5372 S 3.0 1.8 0:16.83 php5-fpm
28422 www-data 20 0 67608 10m 5292 S 2.3 1.8 0:18.99 php5-fpm
28424 www-data 20 0 67352 10m 5368 S 2.0 1.8 0:16.59 php5-fpm
28438 www-data 20 0 67608 10m 5304 S 2.0 1.8 0:17.91 php5-fpm
28439 www-data 20 0 67608 10m 5304 S 2.0 1.8 0:23.34 php5-fpm
28423 www-data 20 0 67608 10m 5292 S 1.7 1.8 0:20.02 php5-fpm
28430 www-data 20 0 67608 10m 5300 S 1.7 1.8 0:15.77 php5-fpm
28433 www-data 20 0 67352 10m 5372 S 1.7 1.8 0:17.08 php5-fpm
28434 www-data 20 0 67608 10m 5292 S 1.7 1.8 0:18.56 php5-fpm
20648 memcache 20 0 51568 8192 708 S 1.3 1.3 2:51.06 memcached
28420 www-data 20 0 69876 13m 6300 S 1.3 2.3 0:20.89 php5-fpm
28421 www-data 20 0 67608 10m 5300 S 1.3 1.8 0:21.19 php5-fpm
28429 www-data 20 0 9524 2260 992 S 1.3 0.4 0:11.68 nginx
28435 www-data 20 0 67608 10m 5304 S 1.3 1.8 0:18.58 php5-fpm
28437 www-data 20 0 67352 10m 5372 S 1.3 1.8 0:17.87 php5-fpm
28441 www-data 20 0 67608 10m 5292 S 1.3 1.8 0:20.75 php5-fpm

Nach einiger Zeit, die irgendwo zwischen einer Sekunde und Minuten liegen kann, verbrauchen plötzlich mehrere (normalerweise zwei) php5-fpm-Prozesse die gesamte CPU:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28436 www-data 20 0 67608 10m 5304 R 48.5 1.8 0:23.68 php5-fpm
28548 www-data 20 0 67608 10m 5276 R 45.2 1.7 0:07.62 php5-fpm
28434 www-data 20 0 67608 10m 5292 R 2.0 1.8 0:23.28 php5-fpm
28439 www-data 20 0 67608 10m 5304 R 2.0 1.8 0:26.63 php5-fpm

An diesem Punkt bleibt alles hängen und alle neuen HTTP-Anforderungen werden beendet. Wenn ich das http_load-Tool stoppe, bleibt das php5-fpm für viele Minuten hängen. Interessanterweise verschwinden die php5-fpm-Prozesse, wenn ich php5-fpm stop tue, aber alle Befehle, die das Dateisystem verwenden, haben Probleme bei der Ausführung. Z.B. Wenn ich versuche, eine Datei über ssh herunterzuladen, zeigt top Folgendes an und dauert einige Minuten, um den eigentlichen Download zu starten:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3298 sshd 20 0 7032 876 416 R 75.2 0.1 0:04.52 sshd
3297 sshd 20 0 7032 876 416 R 24.9 0.1 0:04.49 sshd

Das PHP-Fehlerprotokoll enthält normalerweise Folgendes:

[05-Dec-2012 20:31:39] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 58 total children
[05-Dec-2012 20:32:08] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 66 total children

Das Nginx-Fehlerprotokoll wird mit diesen Einträgen überschwemmt:

2012/12/05 20:31:36 [error] 4800#0: *5559 connect() to unix:/dev/shm/php-fpm-www.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: ..., server: ec2-....compute-1.amazonaws.com, request: "GET /usa/index.php?page=contact_us HTTP/1.0", upstream: "fastcgi://unix:/dev/shm/php-fpm-www.sock:", Host: "ec2-....compute-1.amazonaws.com"

PHP-FPM Slow Log zeigt nichts Interessantes. Tauschen findet nie statt und ich habe keine weiteren interessanten Fakten über das Problem gesammelt. Ich habe viele Iterationen von Konfigurationsdatei-Änderungen durchlaufen, die jüngsten

nginx.conf: http://Pastebin.com/uaD56hJF

pool.d/www.conf: http://Pastebin.com/mFeeUULC

=== UPDATE 1 ===

site config: http://Pastebin.com/qvinVNhB

=== UPDATE 2 ===

Ich habe auch gerade festgestellt, dass dmesg Fehler wie diese meldet

[6483131.164331] php5-fpm[28687]: segfault at b6ec8ff4 ip b78c3c32 sp bff551f0 error 4 in ld-2.13.so[b78b5000+1c000]

=== UPDATE 3 ===

Wir haben eine neue Amazon EC2-Mikroinstanz für den Fall, dass mögliche Hardwareprobleme ausgeschlossen werden. Außerdem verwende ich jetzt php-fastcgi, um mögliche Fpm-Fehler auszuschließen. Andere Unterschiede sind geringfügig, ich denke, das einzige, was sich ändert, ist Ubuntu-> Debian. Dasselbe Problem tritt immer noch auf, mit der Ausnahme, dass es dem Server jetzt gelingt, sich nach den Sekunden von max_execution_time (und dann wieder wieder) wieder etwas zu erholen. 

Ich habe versucht, mit einer separaten test.php zu spielen, und ich bin nicht sicher, ob es sich um dasselbe Problem handelt, aber zumindest in top sieht es genauso aus. Ich habe eine test.php erstellt und eine Reihe von Bibliotheken hinzugefügt, die zu unserem Framework gehören. Die Bibliotheken tun nichts, außer Klassen zu definieren oder andere Bibliotheken einzuschließen, die Klassen definieren. Ich habe bei APC nachgefragt und all das wird erfolgreich von ihm bedient. Ich fing an, test.php mit 200 Anfragen pro Sekunde unter Druck zu setzen, und nach einiger Zeit passierte dasselbe. Nur dass ich jetzt einige Fehler mit der Meldung "zu viele offene Dateien" bekam. Es passiert jedoch nicht immer, manchmal beginnt es einfach mit dem Timeout, ohne dass der Fehler ausgegeben wird, und einige PHP-Prozesse stecken fest und beanspruchen die gesamte CPU. Ich habe nur ein bisschen damit gespielt, aber ich denke, dass hier eine Korrelation besteht. Durch Steuern der Anzahl der enthaltenen Bibliotheken oder geringfügig abweichenden Anforderungen/Sekundenrate kann ich steuern, wann die CPU-Spitze auftritt. Ich habe die relevanten OS-Variablen erhöht, aber das Problem ist immer noch vorhanden, obwohl es länger dauert, bis es geschieht (beachten Sie auch, dass ich die Grenzwerte auf Werte gesetzt habe, die N-mal größer sind als die Gesamtzahl der Anforderungen, die ich während des Tests anfordere).

fs.file-max = 70000
...
*       soft    nofile   10000
*       hard    nofile  30000
...
worker_rlimit_nofile 10000;
...
(reloaded all the configs and made sure the new system vars actually took affect)

Die nächstbeste und einzige Erklärung, die ich bisher finden kann, ist, dass APC zwar Dateien aus dem Speicher ziehen soll, intern jedoch so implementiert ist, dass immer ein Dateideskriptor verwendet wird, wenn PHP include- s werden aufgerufen. Und entweder weil es sie mit einer Verzögerung freigibt oder wenn zu einem unglücklichen Zeitpunkt zu viele Anforderungen zum selben Zeitpunkt eingehen, führt das System unsere Deskriptoren aus und neu eintreffende HTTP-Anforderungen werden schnell in eine große Warteschlange gestapelt. Ich werde versuchen, das irgendwie zu testen.

12
Eugene

Ich habe eine Website mit ähnlicher Konfiguration über viele Monate hinweg ausgeführt, ohne Ausfallzeiten. Ich habe mir deine Config angesehen und sie sieht in Ordnung aus. Davon abgesehen, habe ich vor einiger Zeit meine Konfiguration vorgenommen.

Ich würde in Betracht ziehen, pm.max_requests = 10000 auf etwas vernünftigeres wie pm.max_requests = 500 zu reduzieren. Dies bedeutet nur "nicht jede Instanz für mehr als X Anfragen" verwenden. Es ist gut, diese Zahl nicht zu hoch zu haben, da Sie dadurch eine Widerstandsfähigkeit in Bezug auf mögliche PHP Engine-Fehler erhalten.

Ich denke, das eigentliche Problem liegt höchstwahrscheinlich in Ihren PHP Skripten. Es ist schwer zu sagen, ohne mehr zu wissen.

EDIT: Erwägen Sie, ;request_terminate_timeout = 0 nicht zu kommentieren und auf etwas wie request_terminate_timeout = 20 einzustellen. Ihre Skripts müssen dann innerhalb von 20 Sekunden abgeschlossen sein. Sie werden höchstwahrscheinlich eine Änderung des Verhaltens feststellen, aber ich denke, Ihre Website bleibt auf dem neuesten Stand. Das würde einen PHP Skriptfehler anzeigen.

EDIT2: Meine eigene PHP-Fpm-Konfiguration lautet wie folgt:

[example.com]
listen = /var/run/sockets/example.com.socket
user = www-data
group = www-data
pm = dynamic
pm.start_servers = 5
pm.max_children = 15
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
php_flag[expose_php] = off
php_flag[short_open_tag] = on

EDIT3: Ich habe etwas Unerwartetes in Ihrer Nginx-Konfig entdeckt, aber es kann nichts sein.

Sie verwenden fastcgi_ignore_client_abort on;, was unter älteren Versionen von nginx Probleme in Arbeitsprozessen verursacht. Ich habe dieses Problem nicht selbst gesehen, da ich eine benutzerdefinierte Version einer aktuellen Version ausführte. Hier ist die Beschreibung des Problems auf der Nginx-Site:

In 1.0.2 werden POST-Anforderungen nicht korrekt behandelt, wenn Fastcgi_ignore_client_abort auf festgelegt ist, worauf Worker Segfaulting verarbeiten können. Wenn Sie fastcgi_ignore_client_abort wieder auf Default (aus) setzen, sollte dieses Problem behoben sein.

9
Kevin A. Naudé

Ein einfacher Trick, aber sehr nützlich, um die Prozessorauslastung um bis zu 50% zu reduzieren. Bearbeiten Sie einfach Ihre PHP-Fpm-Konfiguration:

pm = dynamic

und ändern Sie es in:

pm = ondemand
3
Animanga

Ich gehe gerade das gleiche Problem durch und wollte Sie auf diesen Beitrag verweisen:

So bestimmen Sie, welches Skript im PHP-FPM-Prozess ausgeführt wird

Es muss eines Ihrer PHP Skripte sein. Prüfen Sie, ob Sie die Punkte zwischen den durchlaufenden Prozess-IDs und der .php-Skriptdatei verbinden können, die Sie aufhält.

Witzig, das war auf einem Server, der tadellos schnell war. Ich denke, ein WordPress-Upgrade (Plugin oder Core) könnte sehr verantwortlich sein.

1
Berto

Ich hatte das gleiche Problem. Ich habe versucht, PHP-FPM und NGINX neu zu konfigurieren und kam nicht sehr weit. Einer unserer Jungs hat v8js.php ( http://php.net/manual/de/book.v8js.php ) deaktiviert und das Problem behoben. Ich schlage vor, alle PHP-Module zu deaktivieren, bis Sie den Störenfried gefunden haben. Hoffentlich hilft das jemandem.

0
Allen

Das Verhalten von PHP-FPM auf meinem Server ist dasselbe wie Sie. irgendwo sicher ein Engpass.
Die Frage stellt sich: Wie finde ich einen Engpass bei Nginx - PHP-FPM - Mysql? Der schnellste Weg, dies herauszufinden, ist: Aktiviere Slowlog für PHP-FPM.
Fügen Sie die folgenden Zeilen in Ihren php-fpm.conf-Pool ein, und stellen Sie sicher, dass der Pfad vorhanden ist

request_slowlog_timeout = 10
slowlog = /var/log/php-fpm/slow.$pool.log

Durch Lesen des Log-Backtraces können Sie herausfinden, warum PHP-FPM so viel CPU-Zeit oder Timeout aufgewendet hat. Hier sind meine Fälle:

[28-Dec-2018 14:56:55]  [pool laravel] pid 19061
script_filename = /public_html/index.php
[0x00007efdda4d8100] hasChildren() /public_html/laravel/vendor/symfony/Finder/Iterator/ExcludeDirectoryFilterIterator.php:75
[0x00007ffe31cd9e40] hasChildren() unknown:0
[0x00007ffe31cda200] next() unknown:0
[0x00007ffe31cda540] next() unknown:0
[0x00007ffe31cda880] next() unknown:0
[0x00007efdda4d7fa8] gc() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php:91
[0x00007efdda4d7e50] gc() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:159
[0x00007efdda4d7d48] collectGarbage() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:128
[0x00007efdda4d7c20] closeSession() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:79
[0x00007efdda4d7ac8] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Queue.php:47
[0x00007efdda4d7930] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Guard.php:51
[0x00007efdda4d7818] handle() /public_html/laravel/vendor/stack/builder/src/Stack/StackedHttpKernel.php:23
[0x00007efdda4d76e0] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:641
[0x00007efdda4d7598] run() 
/public_html/index.php:51

Das Backtrace erwähnt diese Schlüsselwörter: 

"cookie" "session" "collectGarbage()" "laravel"

Ich suche weiter und TADA, Laravel benutze die RANDOM-Methode, um die abgelaufene Sitzung zu löschen. Und in meiner Konfiguration verwendet PHP SSD, um Session abzuwickeln.
Wenn die Anzahl der Sitzungen "sehr groß" wird, hat PHP mehr Zeit für die Verarbeitung => hoher CPU-Auslastung aufgewendet. 

Wir können viele Engpässe haben, wir können es nur wissen, wenn wir es "debuggen".

Habe ein Nizza untersucht.

0
minhhq