Hintergrundwissen

PHP Queue:

in die PHP-Queue werden alle PHP-Aktivitäten geschoben, die durch IPS abgearbeitet werden (z.B. Scripte). Die Aktivitäten (Threads) werden der Reihe nach abgearbeitet. Ist ein Thread abgearbeitet, fliegt er wieder aus der Queue und mach Platz für einen weiteren Thread. In der Regel geht die Abarbeitung dieser Threads sehr schnell (wenige Millisekunden, also schneller, als neue Threads nachgeschoben werden), so dass es in der Queue eher gemächlich zugeht. Nun ist die Anzahl der Threads in dieser Queue begrenzt (Standard: 10 Threads) und es gibt (böse) Scripte, die deutlich länger brauchen. Gern genommene Beispiele sind hier SLEEP-Befehle in einem Script, die ein schnelles Abarbeiten verhindert. Denn die im Script angegebene SLEEP-Dauer schickt den PHP-Thread in eine Warteschleife und blockiert damit weiterhin den PHP-Thread. Da waren’s nur noch Neun. Jetzt stelle man sich vor, im System gibt es mehrere solcher bösen Scripte, weiterhin kann es schon mal vorkommen, dass ein gewöhnliches Script seinen Job nicht so schnell abarbeiten kann wie gedacht, z.B. weil es auf andere Ressourcen warten muss (Beispielsweise das Abholen von Wetter-Bildern aus dem Web stockt, weil der liefernde Server grad noch schläft). In sehr ungünstigen Konstellationen führt das dazu, dass die PHP-Queue zu ist.

Was passiert dann? -> Dramatisch ist das zunächst nicht, denn die Queue arbeitet seriell nach dem FiFo-Prinzip: neu hinzugekommene Scripte (Threads) werden hinten angestellt und warten, bis wieder ein Thread in der Queue frei wird. Der Anwender merkt dies durch ein verzögert reagierendes System.

 

Was kann /sollte man gegen eine volle PHP-Queue tun?

In erster Linie sollte man Ursachen, die zu einem solchen Systemverhalten führen, abstellen bzw. von vornherein vermeiden: möglichst keine SLEEP-Befehle in Scripts einsetzen (statt dessen lieber Timer-Events verwenden). Ebenso bei Zugriff auf Ressourcen, bei denen längere Wartezeiten zu erwarten sind ist es oft besser, Timer-Events einzusetzen – sofern möglich.

Natürlich kann man – wenn nichts mehr hilft – die Symptome mildern, in dem man zum Beispiel die Anzahl der max. Threads hoch setzt: bis zu 40 Threads sind in IPS V 2.6 möglich. Deren Steuerung ist hier dokumentiert.

 

Soweit kapiert, aber wo ist da ein Problem?

Jetzt kommt es ganz blöd: oben hatte ich nur von funktionierenden Threads/Scripts gesprochen. Blöderweise (Überraschung!)  kommt es aber auch mal vor, dass ein Script so schwere Fehler enthält, dass es sich einfach aufhängt – oder auf ein Ereignis wartet, was nie eintrifft. Diese Threads beißen sich dann auf ewig in der Thread-Queue fest, das System ist (Stand IPS V2.6) nicht in der Lage, diese „DeathThreads“ zu entfernen. Auch Drohungen und Beschimpfungen durch den User helfen hier leider nicht.  Man kann diese DeathThreads in der PHP-Queue (IPS-Konsole, Button „Ansicht hinzufügen“ -> „PHP Informationen“) gut erkennen: sie sind rot hinterlegt (genaugenommen werden Threads dann rot gekennzeichnet, wenn sie die max. PHP-Laufzeit [deafult: 30 Sekunden] überschritten haben -> es sind noch nicht zwingend DeathThreads). Man stelle sich vor: 10 parallele Threads sind möglich, ein DeathThread blockiert aber schon die PHP-Queue. Nun soll aber das IPS möglichst Tage, Wochen, Monate … unbeaufsichtigt laufen und unsere Lebensqualität steigern. Nehmen wir an, das Script – welches als DeathThread hängen geblieben ist – soll einmal täglich laufen: man kann sich leicht an den Fingern abzählen, wie lange das gut geht. Das System wird auf Grund der ständig gefüllten PHP-Queue immer langsamer – bis zum Stillstand. Kurzum: Abhilfe schafft nur ein IPS-Restart.

Und schon kommt der nächste Haken an der Sache: Beim Runterfahren kommt IPS regelmäßig ins Schwitzen: alle während der Laufzeit benötigten Ressourcen müssen abgemeldet, geschlossen, Status geschrieben werden etc etc. Also viel zu tun. Auch hier unterhält sich IPS mit den abzumeldenden Ressourcen: es macht erst dann mit dem nächsten Kandidaten weiter, wenn von der aktuellen, zu schließenden Ressource auch ein „ok – habe fertich!“ kommt. Irgendwann kommen auch die aktiven PHP-Threads an die Reihe. Dem aufmerksame  Leser wird jetzt dämmern: und was ist mit einem DeathThread?? Genau: Tote reden gewöhnlich nicht viel. Genauso auch die DeathThreads. IPS kann jetzt warten, bis es schwarz wird. Und das tut es auch (übrigens schön im Logfile dokumentiert). Im Moment ist es leider so, dass die Settings.json erst nach den zu schließenden PHP-Threads mit aktuellen Daten geschrieben wird – doof, ganz doof. In diesem Fall nämlich nie. Ich warte daher, bis IPS die Settings aus dem Regelbetrieb heraus geschrieben hat und initialisiere unmittebar danach einen IPS-Shutdown. So hab ich wenigstens kein großes zeitliches Delta in den Settingsdaten.

 

Was hat das mir dem DeathThread-Monitoring zu tun?

In dem oben beschrieben Szenario ist solange alles gut, solange noch PHP-Threads zügig abgearbeitet werden können. Auch wird die Settings ohne Probleme während das IPS-Regelbetriebes alle 10 Minuten geschrieben (Standardeinstellung). Problematisch wird es erst, wenn

a)      Ein oder mehrere DeathThreads einen IPS-ShutDown verhindern (und damit ein Schreiben der Settings verhindern)

b)      Das System durch mehrere DeathThreads langsamer wird oder zum Stillstand kommt

 

Da die Symptome derzeit nicht behandelt werden können (entfernen von DeathThreads), sondern nur durch ein IPS-Restart beseitigt werden können, ist es gut, von der Existenz derartiger Störenfriede Kenntnis zu bekommen. Und genau das macht das DeathThread Monitoring: Es beobachtet die PHP-Queue und schlägt Alarm (per Mail an den Admin), wenn es mindestens einen solchen entdeckt hat.

 

IPS RS DeathThread Monitoring – Arbeitsweise

Das DeathThread Monitoring scannt alle paar Sekunden (default_ 37 Sekunden) die PHP-Queue. Es vergleicht den Startzeitpunkt jedes gefundenen Thread mit der aktuellen Uhrzeit. Ist die Differenz größer als 10 Minuten (empirischer Schwellwert! ), wird ein Thread als „DeathThread“ eingestuft und Alarm geschlagen (per Mail und Logfile-Eintrag). Die Anzahl der gefundenen DeathThreads wird in einer separaten Variable festgehalten, ebenso die aktuelle Auslastung der PHP-Queue.

Letztere Kennzahl sollte man zu Beginn des Monitorings etwas im Auge behalten, um ein Geühl zu bekommen, was (bezogen auf das eigene System) „Normalwerte“ sind, und was Grenzwerte sind. Ich habe bei einer max. Thread-Anzahl von 40 einen durchschnittliche Auslastung von 20-30%, es können auch schon mal 50% werden. Solange das nur kurzzeitige Peaks sind, sollte das nicht beunruhigen (schon gar nicht bei einer Messung alle 37 Sekunden [defaultwert]). Ist der Wert aber dauerhaft deutlich über 50% oder steigt kontinuierlich, kann (muss aber nicht) das System schon im roten Bereich sein – was die PHP-Threads angeht. Das sollte man sich auf jeden Fall genauer ansehen.

Um die Logging-DB nicht allzu sehr zu belasten, werden alle DeathThread-Daten, die älter als 48h sind,  automatisch gelöscht.

 

IPS RS DeathThread Monitoring – Installation

Im Download ist ein mit dem IPS RS Project Exporter erstellter Export enthalten, der sehr einfach zu installieren ist:

  • Script aus dem Download ins eigene IPS hochladen und ausführen (keine Konfiguration erforderlich)
  • Es wird vom Script eine Projektinstallation im Zielsystem vorgenommen, die u. A. ein Script mit Config-Daten enthält -> wenn erforderlich, hier Anpassungen vornehmen
  • Nach (optionaler) Konfiguration einmalig manuell das Script „PHP Thread Monitoring“ starten -> Script-Timer wird aktiviert
  • Im WFE installierte Projektelemente von Ebene 0 in gewünschte WFE-Struktur ziehen
  • Optional: das Installations-Script und das erzeugte Installations-Script (als Child vom Installations-Script) aufheben um evtl. spätere Updates zu ermöglichen
  • Fertich!

 

IPS RS DeathThread Monitoring – Quellen

Das IPS RS DeathThread Monitoring beinhaltet zur Darstellung ein geniales, leicht angepasstes Melde-Script zur Darstellung von Messages im WFE (von Horst) aus dem IPS-Forum, Quelle: klick

 


 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

css.php