PHP: Überwachung von Prozessen

In einigen Fällen kann es erforderlich sein, dass ein PHP-Skript nicht mehr wie gewohnt per Request aufgerufen werden soll um dann seine Arbeit erledigt, sondern das es ständig auf dem Server läuft und auf Events wartet. Ein typisches Beispiel hierfür wäre der Client eines Queue-Systems, der beständig auf neue Nachrichten wartet, um sie dann abzuarbeiten.

Beim Auftreten eines Fehlers oder eines Server-Neustarts dürfen sich solche Skripte natürlich nicht einfach nur mit einer Fehlermeldung beenden. Im Gegenteil: Ein solches Verhalten würde das gesamte System zum Erliegen bringen und die Abarbeitung neuer Aufträge solange unterbrechen, bis der Fehler manuell behoben und das Skript wieder gestartet worden ist. Somit muss das Skript also ständig von einem externen Programm überwacht werden, was nicht nur den Fehler erkennt sondern den Prozess auch automatisch neu starten kann.

Für solche Überwachungs-Aufgaben bietet sich beispielsweise Monit an. Monit ist ein einfaches Programm, mit dem eine Vielzahl von Serverdaten und Diensten überwacht werden kann.

Damit Monit unseren Prozess erst einmal überhaupt erkennen kann muss unser Skript beim Starten ein PID-File unter /var/run anlegen. Die nachfolgende Funktion übernimmt diese Aufgabe und legt bei jedem Start eine neue Datei mi dem Namen des Skriptes und der Endung .pid an.

Wenn unser Skript beispielsweise unter /var/www/apache/test_client.php liegt wird also ein PID-File test_client.pid unter /var/run angelegt. In das PID-File wird zudem die aktuelle ProzessID geschrieben, welche unser Skript zum Start zugewiesen bekommen hat.

Achtung: Der User, der das Skript startet muss auch das Recht haben, um nach /var/run schreiben zu dürfen.

Zum starten des Skripts habe ich ein einfaches Shell-Skript test_client.sh angelegt, über das unser Skript getartet sowie ausgegebene Meldungen und Fehler protokolliert werden können.

Achtung: Das Shell-Skript muss ausführbar sein bzw. das Ausführen-Recht besitzen.

Im nächsten Schritt muss Monit die neue Überwachungsaufgabe konfiguriert werden. Dies geschieht, indem wir unter /etc/monit/conf.d/ eine neue Konfigurationsdatei (z.B. test_client.conf) anlegen, in der wir die Aufgabe definieren.

Damit ist alles konfiguriert und wir können zum ersten Test schreiten.

Hierfür starten wir Monit mit /etc/init.d/monit start und prüfen, ob unser Skript nun in der Prozess-Liste auftaucht. (ps aux | grep test_client)

Im zweiten Schritt testen wir, ob unser Skript im Falle eines Fehlers auch automatisch neu gestartet werden würde. Dafür beenden wir die Ausführung des laufenden Skripts mit kill. (kill -9 PID-ID aus der Ausgabe von ps aux) Nach einigen Sekunden sollte Monit das Fehlen des Prozesses erkannt haben und das Skript neu starten. (ps aux | grep test_client)

Wichtig beim Testen: Wenn im zu überwachenden PHP-Skript ein Fehler enthalten ist (Parse-Error, etc.) startet Monit es nur die Anzahl an Restarts, die in der Config-Datei angegeben worden sind. Wenn diese Anzahl überschritten worden ist hilft auch ein Neustart von Monit nicht weiter, da dieses seine Fehlversuche in der Datei /var/lib/monit/state speichert. Es startet das PHP-Skript so lange nicht mehr neu, bis diese Datei gelöscht worden ist. Danach muss Monit via /etc/init.d/moint restart neu gestartet werden.

Damit ist nun sichergestellt, dass sowohl bei einem Server-Neustart als auch bei einem Fehler unser Skript automatisch neu gestartet wird.

Dieses Beispiel deckt natürlich noch lange nicht alle Aspekte ab. Beispielsweise wollen wir trotz der nun geschaffenen Ausfallsicherheit darüber informiert werden, wann und warum unser Skript neu gestartet werden mußte. Auch will der Monit-Dienst selbst überwacht werden (beispielsweise mit Nagios) um sicherzustellen, dass er immer aktiv ist.

Darüber hinaus ergeben sich durch das ständig laufende PHP-Skript Änderungen im Systemverhalten, wenn beispielsweise zum Start des PHP-Skripts eine Datenbankverbindung aufgebaut wird. Dann muss das Skript selbständig erkennen, ob diese Verbindung noch besteht und ggf. erst eine neue Verbindung herstellen, bevor die eigentliche Abarbeitung erfolgen kann. Es gibt also noch eine Menge zu tun. 😉

PHP: Closures

Mit Version 5.3 haben die Closures Einzug in PHP gehalten. Nur, was sind Closures und wie kann man sie verwenden?

Closures konservieren unter Verwendung des Schlüsselwortes „use“ zum Zeitpunkt ihrer Definition die übergebenen Variablen und die darin enthaltenen Werte. Der Inhalt dieser so übergebenen Variablen kann im weiteren Codeverlauf (fast) nicht mehr geändert werden. Das klingt komplizierter als es tatsächlich ist. Hierzu ein kleines Beispiel:

Wie zu erwarten war erhalten wir als Ergebniss 42. Wozu aber der ganze Aufwand?
Hierzu ein weiteres Beispiel:

Das Ergebniss lautet nicht 39 sondern ebenfalls 42. Zum Zeitpunkt der Erstellung des Closures wurde $a fest mit dem Wert 40 im Closure „eingeschweißt“. Eine erneute Wertzuweisung ist danach nicht mehr möglich.

Einem Closure kann auch mehr als eine Variable zugewiesen werden. Hierzu werden diese einfach bei der Definition kommasepariert hintereinander aufgeführt.

In der Einleitung schrieb ich, dass die Werte innerhalb eines Closures (fast) nicht mehr änderbar sind. Da einem Closure aber nicht nur Variablen, sondern auch Referenzen übergeben werden können, bietet sich über diesen Weg noch eine Möglichkeit die Daten nachträglich zu ändern.

In diesem Fall weißt $a also nicht mehr den Wert auf, der bei der Definition des Closures bestand, sondern den Wert, den die Variable $a an der aktuellen Stelle im Skript hat.

PHP: Method-Chaining

Jeder, der in PHP auch nur rudimentär mit Klassen und Objekten arbeitet, kennt solche Aufrufe.

Aufgerufen wird die Klasse nach dem bekannten Schema.

Langweilig! Wirklich intuitiv zu lesen sind diese Ketten von Methodenaufrufen nicht.
Abhilfe kann hier das Method-Chaining (Chaining = Verkettung) schaffen. Hierfür müssen wir im ersten Schritt unsere Klasse etwas umbauen.

Da nun jede der Methoden nicht einfach nur ausgeführt wird sondern die Instanz der Klasse zurückgibt können wir den Aufruf auch wie folgt schreiben.

Das lässt sich doch schon sehr viel besser lesen oder? Aus diesem Grund spricht man hierbei auch vom „Fluent Interfaces“, da man so annähernd in Form von Sätzen wie in der natürlicher Sprache programmieren kann. Zur besseren Lesbarkeit kann man die einzelnen Methoden auch untereinander schreiben, wenn man mag.

Auf diese Weise kann man mit dem Method-Chaining besser lesbaren Code erzeugen, der dem natürlichen Satzbau schon sehr nahekommt. Damit werden viele Anwendungsfälle, wie beispielsweise die nachfolgende Datenbankabfrage, schneller verständlich.

Die Vorteile, die uns das Method-Chaining bietet liegen somit auf der Hand:

  1. Durch die bessere Lesbarkeit entfällt ein Teil der notwendigen Dokumentation.
  2. Dank des satzähnlichen Aufbaus bekommt man schneller eine Vorstellung von der Verwendung und dem Gebrauch der einzelnen Methoden.

Diese Art der Programmierung bringt aber auch Nachteile mit sich, die vorher bekannt sein sollten und berücksichtigt werden wollen:

  1. Die Methoden müssen nicht in der gezeigten Reihenfolge aufgerufen werden. Das erschwert zum Einen die Programmierung der Klasse als auch das Abfangen von Fehlern, wenn die Methoden nicht wie geplant verwendet werden.
  2. Die langen Ketten von aufeinander aufbauenden Methoden erschweren das Debugging.

PHP: Coding Standards

In vielen PHP Projekten sieht es aus wie Kraut und Rüben. Da werden die Variablen nach Lust, Laune und Tagesform benannt, die Benennung der einzelnen PHP-Dateien und der darin befindlichen Code-Teile erfolgt keinem erkennbaren Muster und die Notation der einzelnen Klassen, Methoden und Funktionen wechselt wild zwischen verschiedenen Groß- und Kleinschreibungen sowie unterschiedlichen Bezeichnern, gemixt aus Deutsch und Englisch.

Je größer ein solch organisch gewachsenes Projekt wird, desto mehr und mehr Zeit verschlingt es alleine bei der Wartung und Pflege. Diese Richtlinien helfen bei der besseren Zusammenarbeit von mehreren Entwickler am gleichen Projekt. Auch die Zeit, die ein neuer Entwickler benötigt, um sich ein-, anstatt bereits produktiv mitzuarbeiten, wird hierdurch verringert. Zudem erleichtert eine einheitliche Code- und Projekt-Struktur die Entwicklung und Nutzung von auch in anderen Projekten nutzbaren Komponenten, wie sie heutzutage in Frameworks wie Symfony oder dem Zend Framework üblich sind.

Aus Gründen wie den oben genannten hat die PHP-FIG (PHP Framework Interop Group) in den Standards PSR1 und PSR2 verbindliche Coding Standards definiert, um solche Probleme von vornherein zu vermeiden.

PSR1: Basic Coding Standard

  1. Dateien dürfen nur den „<?php“ oder den „<?=“ Tag verwenden.
  2. PHP-Dateien dürfen nur UTF-8 ohne BOM (Byte Order Mark) verwenden.
  3. Dateien sollten entweder Klassen, Funktionen, Konstanten, etc. definieren oder einen Effekt – wie eine Ausgabe generieren oder Einstellungen der php.ini zu überschreiben – haben. Sie sollten aber nicht Beides gleichzeitig machen.
  4. Namespaces und Klassen müssen dem „autoloading“-PSR-Standard folgen.
    (Definiert in PSR-0 und PSR-4)
  5. Klassennamen müssen mit einem Großbuchstaben beginnen und dürfen nur im StudlyCaps-Format benannt werden.
  6. Konstanten in Klassen müssen komplett groß geschrieben werden, als Seperator ist nur der Unterstrich erlaubt.
  7. Methoden in Klassen dürfen nur im Camelcase-Format bezeichnet werden.

PSR2: Coding Style Guide

Dieser deutlich umfangreichere Standard erweitert den vorherigen Standard PSR1.

  1. Die Vorgaben aus dem PSR1: Basic Coding Standard müssen eingehalten werden.
  2. Für Codeeinrückungen dürfen keine Tabs, sondern immer nur 4 Leerzeichen verwendet werden.
  3. Es darf kein festes Limit für Zeilenlängen geben. Das Soft-Limit muss bei 120 Zeichen liegen und Zeilen sollten nicht mehr als 80 Zeichen haben.
  4. Es muss jeweils eine Leerzeile nach der Namespace-Deklaration und nach dem Block der use-Deklarationen eingefügt werden.
  5. Die öffnende, geschweifte Klammer einer Klasse muss in der Zeile nach dem Klassennamen stehen und die schließende, geschweifte Klammer muss in der nächsten Zeile nach dem Klassenkörper stehen.
  6. Die öffnende, geschweifte Klammer einer Methode muss in der Zeile nach dem Methodennamen stehen und die schließende, geschweifte Klammer muss in der nächsten Zeile nach dem Methodenkörper stehen.
  7. Die Sichtbarkeit muss für alle Eigenschaften und Methoden deklariert werden. abstrakt und final muss vor der Sichtbarkeit; static muss nach der Sichtbarkeit deklariert werden.
  8. Schlüsselwörter von Kontrollstrukturen müssen von einem Leerzeichen gefolgt werden. Es dürfen jedoch keine Leerzeichen nach Methoden- oder Funktionsaufrufen verwendet werden.

  9. Bei Kontrollstrukturen muss die öffnende, geschweifte Klammer in der selben Zeile und die schließende, geschweifte Klammer muss in der nächsten Zeile nach dem Strukturkörper stehen.
  10. Öffnende Klammern für Argumente von Kontrollstrukturen dürfen nicht von Leerzeichen gefolgt werden und vor der schließenden Klammer darf ebenfalls kein Leerzeichen stehen.

Quellen:
[1] PSR-1: Basic Coding Standard
[2] PSR2: Coding Style Guide

PHP: Singleton Pattern

Die Idee, die hinter dem Singleton-Entwurfsmuster steckt, ist simpel. Es soll erreicht werden, dass von einer Klasse nur eine Instanz erzeugt werden kann und die Erstellung weiterer Instanzen nicht mehr möglich ist. Nur, wofür brauche ich das und wo kann ich es einsetzen?

Ein Beispiel für den praktischen Einsatz des Singleton Entwurfsmusters sind Datenbank-Verbindungen. Der Aufbau jeder Verbindung zur Datenbank benötigt Zeit und Ressourcen des Servers. Was liegt also näher, als das wir beim ersten Query an die Datenbank unserer Anwendung eine Verbindung zur Datenbank öffnen lassen und im weiteren Programmablauf dafür sorgen, dass immer nur diese Verbindung verwendet wird? Genau hierbei hilft uns das Singleton-Entwurfsmuster.

Aber schauen wir uns das einmal im Code an:

Aufgerufen wird die Klasse dann so: