Performanceoptimierung PHP wait load

klodeckl

New Member
Hallo,

ich hätte da ein Problem hinsichtlich der Performance. Bei manchen TYPO3 Systemen auf meinem Server habe ich teilweise recht lange Ladezeiten, insbesondere nachdem der Cache gelöscht ist, aber auch so, Hauptsache der APC hat es nicht im Cache. Genau, der APC ist auch installiert und bekommt sogar ein ganzes GB nur zum cachen. Sobald der APC greift, rennt er ohne Ende. Wenn nicht kann es schonmal zu 8 bis 30 Sekunden Wartezeit kommen. In der Zeit ist dann immer die CPU wait load ziemlich hoch wenn ich mir mit top die Auslastung ansehe. Ich kann mir aber nicht erklären woher die wait load kommt. Andere nicht T3 Systeme sind schon flotter, z. B. ein Magento geht recht flott, aber während des Aufrufs sehe ich auch hier, das die wait load kurzzeitig schonmal auf 20 bis 50 % ansteigen kann. Ich habe aber auch das Gefühl, dass es speziell mit dem 6er Zweig von TYPO3 am schlimmsten ist (irgendwie wird doch jede neue Version langsamer).

Zum System, das ist ein i5 mit 16 GB RAM, Debian 6 mit Plesk 11, PHP 5.3.25 (mit APC) und MySQL 5.5. Apachemodule sind natürlich auch einige drauf. Die Domains laufen entweder als Fastcgi oder Apache Modul.

Viele Dank für eure Hilfe! Grüße
Bernhard
 
Uff, PHP ist so eine Spezielle Geschichte, zumal mit diversen Zusatzplugins der jeweiligen Software (Ob es nun Typo, Magento oder auch andere Systeme sind) viel Müll fabriziert werden kann. So einige Plugins sind meist unsauber geschrieben die das System dann aufhängen lassen können.

Hast du mal eine Standardinstallation angeschaut gehabt? Wenn es da schon nicht flott funktioniert, liegt es möglicherweise an der Serverkonfiguration.

Tipp: Mal APC komplett ausschalten, notfalls alternativen nutzen - Ich z.B. nutze eAccelerator was durchaus um einiges schneller ist. Wie schaut denn deine PHP Konfiguration aus?

Schonmal einen Network-Trace gemacht um vllt. zu schauen ob das "lange Laden" nicht auch durch zu vielen Redirects verursacht wird? Beim tracen völt. auch mal drauf achten, welche Files arg lange benötigen um geladen zu werden.
 
Also es tritt beispielsweise auch bei einem frisch installiertem Introduction Package von TYPO3 auf, dass es irgendeine Erweiterung/Modul macht, glaube ich daher weniger, es tritt auch auf mehreren Systemen auf und nicht nur auf einem.

Also mit APC bin ich eigentlich sehr zufrieden, die langen Ladezeiten und CPU wait load kommen nur, wenn der APC mal nicht greift. Ich bevorzuge auch APC, da es einfach installiert ist, Bestandteil von PHP wird/ist und viele APC Befehle von z. B. TYPO3 genutzt werden.

Ich dachte bis jetzt eher immer an Apache-Tuning. Hier meine aktuelle Konfig vom Apache:
Code:
Timeout 300
KeepAlive On
KeepAliveTimeout 7
    StartServers          5
    MinSpareServers       8
    MaxSpareServers      80
    ServerLimit		400
    MaxClients          400
    MaxRequestsPerChild   0
Was wäre denn von der php.ini interessant? Ich kann ja nicht gleich die ganze Datei posten. Memory Limit ist auf den meisten vhosts auf 256, Minimum aber 128, die betroffenen haben auf jeden Fall 256. Die Konfig vom APC ist:

Code:
; configuration for php apc module
extension=apc.so
; Es sollen Informationen über den Hochladevorgang gespeichert werden.
apc.rfc1867 = On
; Benutze upload_ als Präfix für den Eintrag im Zwischenspeicher.
apc.rfc1867_prefix = upload_
; Name des versteckten Formularelementes, welches diese Funktionalität aktiviert.
apc.rfc1867_name APC_UPLOAD_PROGRESS
;## PHP file cache 2 hours ##
apc.ttl=7200
;## User cache 2 hours ##
apc.user_ttl=7200
;## Garbage collection 1 hour ##
apc.gc_ttl=3600
;apc.shm_size=1280M
apc.shm_size=1024M
apc.max_file_size = 2M
;Relative to the number of cached files (you may need to watch your stats for a day or two to find out a good number)
apc.num_files_hint=7000
apc.user_entries_hint=4096
my.cnf:
Code:
key_buffer		= 16M
max_allowed_packet	= 16M
thread_stack		= 192K
thread_cache_size       = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover         = BACKUP
max_connections        = 250
table_cache            = 4096
table_definition_cache = 4096
max_heap_table_size = 32M
tmp_table_size = 32M
query_cache_limit	= 2M
query_cache_size        = 192M
join_buffer_size = 192K
init_connect = 'SET collation_connection = utf8_general_ci'
init_connect = 'SET NAMES utf8'
innodb_buffer_pool_size=768M
innodb_additional_mem_pool_size=500K
innodb_log_buffer_size=500K
innodb_thread_concurrency=2

Ich befürchte gerade, dass es weder mit dem Apache, noch mit MySQL zusammenhängt. Ich habe nämlich gerade den folgenden Befehl am laufen:
mysqlcheck -uadmin -p`cat /etc/psa/.psa.shadow` --auto-repair --optimize
Dabei fällt mir ebenso eine hohe wait Last auf. Im Anhang sind zwei Screenshots dazu, die dies verdeutlichen.
Was kann da noch der Auslöser sein? Das einzige was mir einfällt, dass die Festplatte evtl. zu langsam ist?
 

Attachments

  • cpu-top.png
    cpu-top.png
    224.7 KB · Views: 275
  • cpu-nmon.png
    cpu-nmon.png
    46.3 KB · Views: 290
Kann es sein, dass PHP auf Netzwerk- oder Dateisystem-IO wartet?
Nicht dass einfach die Netzwerkverbindung zum MySQL-Server obszön lange dauert oder irgendwelche PTRs beim Verbinden nicht richtig aufgelöst werden können.
 
Load Gurke, guter Tipp.
Pass auf, des hatte wohl jemand aus dem PHP-Forum bzw. Java-Forum - Der hatte auch eine unheimliche Ladezeit, bis er mal den Hostnamen der SQL Server geändert hatte. Die standen zuvor auf Domain- bzw. Hostname-Ebene was durch mögliche DNS Auflösungsversuche zu längerer Ladezeit kam. Einfach mal dieekt die IP bzw Lokale IP (127.0.0.1) verwenden.

Im übrigen wären weitere System-Infos hilfreich:
Welche Apache-Module werden genutzt, Welches OS (32 oder 64 bit?), RAM, CPU, auch was für eine MySQL version du hast(32/64bit?).

Auch ist 128 bzw. 256 MB als memory limit etwas zu hoch.
Das Musste ich auch bei mir feststellen - Jede PHP instanz die durch einen Browseraufruf stattfindet verwendet bzw. reserviert diese. Wenn du also nur 2 GB Arbeitsspeicher verbaut hast ist bei 16 Besuchern schluss.

Gleiche thema war bei mir der Fall, und das bei einem Website-System was von mir programmiert wurde, für einen Hoster der eindeutig mehr Ressourcen benötigt. Zwar war reichlich verbaut, aber wenn das memory limit so hoch liegt, kann das durchaus knapp werden.

Tipp: Lass mal Mysqltuner.pl durchlaufen.
 
Also an den Resourcen liegt es nicht, das ist ein i5 mit 16 GB RAM, da gibts genügend Reserven damit ich 256 MB zuweisen kann.

Kann es sein, dass PHP auf Netzwerk- oder Dateisystem-IO wartet?
Das vermute ich eben auch. Aber warum weiß ich noch nicht. MySQL läuft auf dem localhost und so gebe ich auch immer die Verbindung an (localhost). Als ich mysqlcheck via SSH ausgeführt habe und die wait Last auch da so hoch war, habe ich mich auch mit localhost verbunden. nmon zeigt mir zumindest, dass dann auch die Festplattenaktivität kurz hoch geht. Kann es mit dem Dateisystem bzw. der Festplatte zusammen hängen?

Das System ist ein Debian 6, 64-bit mit Plesk 11.0.9, Apache 2.2.16 (prefork), PHP 5.3.26, MySQL 5.5.31.

Tipp: Lass mal Mysqltuner.pl durchlaufen.
Das mache ich schon öfter, dadurch habe ich MySQL optimiert. Ich habe nur den tuning-primer.sh verwendet, sollte aber auf das selbe raus kommen.


Geladene Apache-Module:
Code:
apache2ctl -M
Loaded Modules:
 core_module (static)
 log_config_module (static)
 logio_module (static)
 mpm_prefork_module (static)
 http_module (static)
 so_module (static)
 aclr_module (shared)
 actions_module (shared)
 alias_module (shared)
 auth_basic_module (shared)
 auth_digest_module (shared)
 authn_file_module (shared)
 authz_default_module (shared)
 authz_groupfile_module (shared)
 authz_host_module (shared)
 authz_user_module (shared)
 autoindex_module (shared)
 cgi_module (shared)
 dav_module (shared)
 dav_fs_module (shared)
 dav_lock_module (shared)
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 fcgid_module (shared)
 headers_module (shared)
 include_module (shared)
 mime_module (shared)
 negotiation_module (shared)
 perl_module (shared)
 php5_module (shared)
 python_module (shared)
 reqtimeout_module (shared)
 rewrite_module (shared)
 rpaf_module (shared)
 setenvif_module (shared)
 ssl_module (shared)
 status_module (shared)
 suexec_module (shared)
 userdir_module (shared)
Syntax OK

Auf dem Server wird Webhosting mit verschiedenen Domains ausgeführt.
Ach ja, es sind zwei 500 GB Platten verbaut, die zweite wird jedoch nur als Backupplatte verwendet, also kein Raid.
 
Last edited by a moderator:
Verbindung an (localhost)
Probier mal die IP bzw Lokale IP 127.0.0.1

Wie ich bereits schrieb hatte da jemand Probleme, dass unter "localhost" zu lange ladezeiten aufkamen, weil der DNS versucht hat "localhost" aufzulösen...

Apache-Module sind soweit auch kein Problem.

Dein MySQL ist auch eine 64bit installation richtig? - Deswegen schrieb ich, ob du diese infos auch mitgeben kannst!?
Wenn nicht dann hast du dort das Problem sitzen. 32bit MySQL hat probleme mit der Speicherverwaltung, wenn es auf einem 64bit system läuft.
 
Das ist die 64-bit Version von Debian, daher denke ich wird MySQL von apt auch in der 64-bit Version installiert sein.

Ich habe deinen Tipp mit 127.0.0.1 statt localhost soeben mal versucht, macht keinen Unterschied. Bei mysqlcheck wars auch so.

Es wird jetzt in der Nacht mal ein Hardware Check durchgeführt. Ich befürchte, dass es an der Festplatte liegt, ansonsten wäre ich ratlos. Habt ihr noch Tipps falls es das nicht ist?
 
Falls sehr viele Dateien geöffnet werden (ob lesend oder schreibend ist egal), kann es viel bringen, wenn auf dem betreffenden Dateisystem die Mountoption "noatime" gesetzt wird. Damit werden dann keine lesenden Dateizugriffe mehr in die Metadaten der Datei geschrieben was die Sache etwas beschleunigen kann.

Da die Wait-Time bei dir extrem hoch ist, tippe ich mal darauf dass der auf die Fertigstellung irgendwelcher Festplattenoperationen wartet - und wenn die Festplattenqueue voll ist und nicht so schnell abgearbeitet werden kann...
Btw: Welches RAID-Level hast du denn darunter? Festplattenpartitionen auf 4k-Sektorgrößen ausgerichtet (aligned) ?

Ist das ein virtualisiertes System? Wenn ja: Welche Virtualisierungstechnologie?
Bei KVM z.B. bringt es echt Schub, wenn man die Host-CPU 1:1 durchreicht. Sonst sieht die CPU im Gast nur ein paar wenige Befehlssätze und muss unnötigerweise aufwändigere Rechenoperationen anstoßen als wenn der optimierte Befehlssatz genutzt wird. Gerade die Generierung von Vorschaugrafiken etc... bekommt damit mehr Power.

GZIP-Kompression im PHP-Script, in der php.ini und im Apache deaktiviert?
Schalte es überall, außer im Apache aus. Macht keinen Sinn dass an drei Stellen komprimiert wird...

Wird die CPU heruntergetaktet? Einfach mal die automatische Taktregelung ausschalten, auf "volle Pulle" stellen und nochmal versuchen.

Ansonsten mal testen:
Korrekte DNS-Server eingetragen? Antworten die auch (schnell)?
Kann der Server seinen eigenen Hostnamen und seine eigene IP auflösen?
Werden bei jedem Zugriff parallel irgendwelche riesengroßen Debug-Logs geschrieben?
Irgendwelche Apache-Module die nicht zwingend gebraucht werden?
 
Last edited by a moderator:
Gib mal bitte die Mountparameter an und auch wie schnell du kleine Blocke auf die Platte schreiben kannst (z.B. mit dd).
 
Hier die Einträge der fstab:

Code:
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
# / was on /dev/sda2 during installation
UUID=c0e04469-fa8e-4b92-bbcb-db547299addd /               ext4    errors=remount-ro 0       1
# /disc2 was on /dev/sdb2 during installation
UUID=98b3eef0-a780-4e2e-a154-fc3db4f7d3d3 /disc2          ext4    defaults        0       2
# swap was on /dev/sda1 during installation
UUID=5cdaec78-5de0-4179-90dd-c1e7e3a0a10e none            swap    sw              0       0
# swap was on /dev/sdb1 during installation
UUID=47235b57-05d4-43ad-9cbc-7c877967cdca none            swap    sw              0       0
/dev/scd0       /media/cdrom0   udf,iso9660 user,noauto     0       0

Das ist derzeit KEIN Raid System, es sind zwar zwei Platten verbaut, die zweite wird jedoch als Backup verwendet. Heute Nacht wird der Hardware Check durchgeführt, falls die Platte getauscht werden würde, würde ich sie wahrscheinlich gleich in ein RAID klonen (evtl. dann noch eine dritte Platte, damit ich trotzdem noch eine Backupplatte habe). Was würdet ihr hier empfehlen? Das mit den Sektorgrößen, keine Ahnung, wie schaue ich das nach (Erstinstallation machte natürlich der Provider)?

Virtuelles System ist es nicht, ist eine richtige Maschine, die im RZ steht. Daher komme ich auch nicht aufs BIOS drauf und kann daher nichts mit der Taktregelung einstellen. An der GZIP Kompression liegt es normalerweise auch nicht, die wird auf einigen Seiten gar nicht verwendet und das Problem ist trotzdem da (ja auch bei mysqlcheck). DNS sieht auch gut aus, löst flott auf und von Debug-Logs ist mir nichts bekannt. Die Apache Module bräuchte ich denke ich schon, da ich ja Hosting anbiete, da muss ich ja die Module anbieten.

Wie mache ich das mit dem Blockschreibtest mit dd (ohne dass ich was lösche)?

Bugl der vielen offenen Dateien, ab wann kann man viel sagen? Gerade sind es 18673, was denke ich schon viel ist und wahrscheinlich durch das Caching kommt, das ich so hoch gedreht habe. Dann macht es wahrscheinlich schon Sinn, noatime zu setzen.
 
Daher komme ich auch nicht aufs BIOS drauf und kann daher nichts mit der Taktregelung einstellen.
Bei einem vernünftiger Hoster schon, ich habs beispielsweise. Ich kann direkt ins BIOS und aber auch remote direkt zum terminal der am Server klemmt.

Wie mache ich das mit dem Blockschreibtest mit dd (ohne dass ich was lösche)?
Das mit den Sektorgrößen, keine Ahnung, wie schaue ich das nach (Erstinstallation machte natürlich der Provider)?
Als Hoster scheinst du ja nicht sehr geschult zu sein, wenn du nicht weist wie man Platten checkt ^^ Und ich denke dies ist auch der yhauptgrund warum du Probleme hast: Zu wenig Ahnung.

Im übrigen:
Die Installation musst du machen, nicht der Provider/Hoster.
1. Backups anlegen
2. Platten austauschen lassen
3. Neu aufsetzen
 
Wie mache ich das mit dem Blockschreibtest mit dd (ohne dass ich was lösche)?

Ich gehe davon aus, dass die DB unter /var liegt. Dann versuch es mal mit
Code:
dd if=/dev/zero of=/var/file bs=32k count=5000 oflag=sync

Als mögliche Mountoptionen solltest du dir mal noatime,nobarrier ansehen.
 
Aaahhh!!
nobarrier bitte nur aktivieren, wenn du einen RAID-Controller mit BPU (Batteriepuffer) hast, wovon ich jetzt gerade nicht ausgehe.
Sonst hast du eine nahezu 100%ige Chance, dass deine Datenbanken nach einem Stromausfall kaputt sind.
 
Der Hauptgrund war ein Festplattendefekt. Diese wurde nun getauscht und dann gleich ein Raid 1 gemacht. Jetzt habe ich nur das Problem, dass das Backup, das ich vorher erstellt habe, sich nicht einspielen lässt. Beim ersten mal hat er ein paar Sachen eingespielt und dann aber Fehler gebracht. Anscheinend sind die Passwörter nicht im Backup, zumindest will er laut Protokoll die DB User anlegen, im Befehl dazu wird aber das Passwort nicht übertragen und dann gibts ne Fehlermeldung. Das anschließende Einspielen der DBs klappt dann nicht, da er den User dazu nicht hat. Bei einem weiteren Anstoßen des Wiederherstellens geht es beim Domain Mapping auf einmal nicht mehr weiter, so dass er nicht los legt. Jetzt waren neben mir auch schon fünf Techniker vom RZ dran und keiner weiß gerade Rat. :-(
 
Vielleicht hast Du deinen Technikern ja, genau wie uns, die Fehlermeldungen vorenthalten :)

So ganz ohne harte Infos (Backup wie gemacht, welcher Befehl zum Einspielen, Logs und Fehlermeldungen etc). können wir das auch nicht.
 
Nee, habe ich nicht, die haben auch selbst Zugriff darauf und ich habe jeden Hinweis weitergegeben.

Das Backup wurde über die Pleskoberfläche erstellt. Das Einspielen wurde sowohl von mir, als auch von den versierten Technikern über die Oberfläche, als auch über SSH versucht einzuspielen. Beim ersten Einspielen über die Oberfläche hat er ein paar Sachen importiert, dann hat das Backup abgebrochen. Ab dem zweiten mal über die Oberfläche ging es nach der Auswahl des Domain Mappings einfach nicht mehr weiter und über SSH kam dann die folgende Meldung:
Code:
Traceback (most recent call last): 
File "/opt/psa/admin/sbin/pmmcli", line 6, in <module> 
pmmcli.main() 
File "/opt/psa/admin/share/pmmcli/pmmcli.py", line 2283, in main 
_logger.critical("PMMUtility exception: \n" + str(unicode(e)) + "\n" + stacktrace.stacktrace()) 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1120-1124: ordinal not in range(128) 
Failed to parse response. Reason: Failed to read data from stream Process output:

Irgendwann wurde das dann aufgegeben und ich bin seit gestern nur daran, die ganzen Sachen aus dem Backup manuell anzulegen und zum Laufen zu bringen. Mittlerweile habe ich zumindest das Wichtigste wieder da, aber eben super Zeitaufwändig. Der Support von Parallels war heute auch schon dran (vielleicht sogar immer noch), haben aber bisher auch noch nichts konkret gemacht und keine konkreten Aussagen gemacht.

Weil ich das jetzt schon manuell mache, wäre es interessant für mich zu wissen, wie ich das im Backup stehende verschlüsselte Passwort (z. B. für Mailaccounts) in Klartext umwandeln kann, damit ich nicht die Passwörter für die Kunden ändern muss. Habt ihr da eine Idee?
 
Weil ich das jetzt schon manuell mache, wäre es interessant für mich zu wissen, wie ich das im Backup stehende verschlüsselte Passwort (z. B. für Mailaccounts) in Klartext umwandeln kann
Ohne jetzt die aktuellen Plesk-Versionen zu kennen, so ist ein Passwort generell nicht verschlüsselt sondern gehasht. Falls es ein simpler MD5 ist hast du bei einigen Kunden vielleicht Glück mit Rainbow-Tabellen, bei salted md5 oder gar SHA,.... geht das aber nicht mehr.
 
Hierzu
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1120-1124: ordinal not in range(128)
habe ich einen Hinweis gefunden, man soll aus den Namen bzw. Beschreibungen der Backups die Sonderzeichen entfernen soll. Keine Ahnung ob das hier auch zutrifft.

Zu den Passwörtern, man kann einfach den Hash nehmen und diesen manuell bzw. per Skript in die Felder in der Datenbank schreiben, damit stellt man den Urzustand wieder her (d.h. Kundenpasswort wird wieder vom System akzeptiert) ohne die Passwörter in Klartext zurückrechnen zu müssen.

viel Erfolg,
Nils
 
Back
Top