Eltern haften für ihre Kinder

Releasewechsel in PHP

Offensichtlich stellt die Auslieferung ein neuen Releases in einigen PHP-Projekten einen hohen manuellen Aufwand dar, da Dateien über die bestehende Installation mehr oder weniger manuell kopiert werden. Dabei müssen selbstverständlich zu löschende Dateien und Ordner berücksichtigt werden, sowie ist darüber hinaus dieser Vorgang nur vorwärtsgerichtet und kann im Falle eines massiven Fehlers nur zurückgerollt werden sofern eine Komplettsicherung vorliegt.
Zu guter Schluss kann dieser manuelle Vorgang mehrere Minuten bis sogar Stunden in Anspruch nehmen und damit eine längere Downtime der Webseite bzw. des Services einfordern. Je nach Projekt kann dies unerwünscht und in Folge dessen auch noch mit hohen Kosten verbunden sein – zum einen durch Personalkosten sowie zum anderen der Nichtverfügbarkeit und dem damit verbundenen Nutzungsausfall. Wer zur Krönung dann noch eine ganze Farm von installierten Applikationen zu aktualisieren hat wird letztlich seinen Aufwand nochmal um die Anzahl der Hosts multiplizieren dürfen.

In diesem Sinne: Prost Mahlzeit!

Ein völlig anderer Ansatz ist es den statischen Anteil eines Releases, welcher sich in Form der ausführbaren PHP-Skripten und den auszuliefernden Dateien ausdrückt über einen symbolischen Link herzustellen.

Vorgehensweise

Dafür muss zunächst die Projektstruktur in Form gebracht werden. Das kann je nach Applikation mehr oder weniger Aufwand bedeuten und lässt sich in folgende Schritte untergliedern:

  • Der bestehende Codestand wird zunächst in ein Unterverzeichnis namentlich “wwwroot” verschoben, sofern das Projekt noch nicht in dieser Hierarchie strukturiert vorliegt. Dies ist dann auch künftig die einzurichtende Webroot auf allen neuen Systemen.
  • Systemspezische Ordner die lokale Daten des jeweiligen Systems beinhalten würden an dieser Stelle verbleiben. Das betrifft zum Beispiel Arbeitsdaten, Temporäre, Cache-, Logging- und Konfigurationsdaten.
    releasewechsel-development
  • Im Produktivbetrieb wird nun – anders als in der Entwicklung – auf dieses Release verwiesen indem ein separater Ordner releases in Höhe wwwroot bzw. der systemspezifischen Web-root angelegt wird. Jedes Release wird hier drin in einem weiteren Unterordner abgelegt der namentlich die Revisionsnummer oder die Version beinhaltet.
    Releasewechsel Releases
  • Initial wird nun erstmalig das aktuelle Release im Ordner releases nach wwwroot verlinkt.
    Releasewechsel Hauptverzeichnis
  • Unabhängig von dieser Beschreibung sollten darüber hinaus alle extern abzurufenden Daten wie z.B. Javascript, Bilder und CSS Skriptseitig noch ein Versions- oder Revisionspostfix angehangen werden. Dieser wird in einer Release-spezifischen Konfigurationsdatei mit jedem eigenen Release gesetzt und sodann ausgelesen. Durch diesem Mechanismus werden beim Abruf einer bereits aktiven Session auch die richtigen Daten abgerufen, da der Browsercache des Users in der Regel gleichnamige Dokumente nicht erneut lädt.
    Das könnte zum Beispiel für die Verlinkung eines JS-Files wie folgt aussehen:

    <script type='text/javascript' src='js/jquery.js?ver=2.2.3'></script>
  • XHR-Requests wie typischerweise JSON und XML sollten abschließend immer einen eindeutigen Kenner in der URL mitliefern damit weder Client- noch Servercache auf die Idee kommen bereits generierte Daten wiederzuverwenden. Dafür eignet sich hervorragend das clientseitige Anreihen des Zeitstempels in Millisekunden an jede URL via Javascript:
    var url = "http://moderlak.de/releasewechsel-in-php/?" 
            + new Date().getTime()

    Grundsätzlich muss man sich um diese Problematik nicht kümmern, da viele Frameworks diesen Vorgang bereits von Haus aus erledigen. Ich möchte es nur der Vollständigkeit halber für diejenigen benennen, die AJAX-Requests noch händisch zusammensetzen oder ein eigenes Framework verwenden, welches diese Methodik noch nicht implementiert.

Das Verzeichnis wwwroot entspricht hiermit allerdings noch nicht dem öffentlich zugänglichen Teil der Software. Dies kann und sollte unbedingt nochmal über ein weiteres Unterverzeichnis wie zum Beispiel public zugeordnet werden.

Releasewechsel vornehmen

Vom Prinzip her beinhaltet der Wechsel folgende Schritte:

  • Neues Release im Ordner releases in eigenen Unterordner ablegen
  • Bestehenden Symlink wwwroot entfernen, sofern vorhanden
  • Neuen Symlink wwwroot auf das gewünschte(aktuelle) Release setzen
  • Apache graceful neustarten, damit dieser den neuen Symlink erkennt, jedoch kein Benutzer den Neustart bemerkt – Wer seinen Webserver im IIS laufen lässt muss den zugehörigen Container neustarten
  • Applikationscache leeren
  • Zugehörige Datenbankupdates der Applikation durchführen
  • Gegebenfalls ältere Releases löschen – den vorherigen jedoch sollte man stets zurücklassen um auf diesen im Notfall zurückspielen zu können, falls mit der Softwareaktualisierung eine massive Störung einhergeht und diese mit einer Wiederherstellung des letzten Standes behoben werden kann.

Dieser ganze Vorgang kann dann noch in einem bzw. mehreren Skripten zusammengefasst werden um den Auslieferungsprozess zu vereinfachen. Damit lässt sich der gesamte Vorgang auf eine einzige Aktion hinunterbrechen. Erfahrungsgemäß kann ein solcher Wechsel sodann innerhalb von wenigen Sekunden abgeschlossen werden.

Dabei ist es unerheblich ob dies auf einem Windows– oder Linuxsystem vorgenommen wird. Es ist nur der jeweilige Befehl wie dieser Link erzeugt wird, denn beide Betriebssysteme unterstützen symbolische Links.

Unter Windows erfolgt die Verlinkung auf diesem Weg:

mklink /D ./releases/moderlak.de-1.2.3 ./wwwroot

In Linux mit diesem Befehl:

ln -s ./releases/moderlak.de-1.2.3 ./wwwroot

Fazit

Ein Release wird atomar und innerhalb von Sekunden gewechselt. Dabei bemerken die Benutzer den Relasewechsel höchstens in Form einer verlängerten Antwort während des Neustarts der Webserverinstanz. Die Dateien eines Releases bleiben stets zusammen und es werden keine Dateileichen zurückgelassen.
Sollte ein Releasewechsel akut Probleme verursachen, kann sekundenschnell auf das alte Release zurückgeschaltet werden (Vorausgesetzt bereits gelaufene Updates haben keine Datenbankänderungen vorgenommen, die dies auf dem älteren Codestand unmöglich machen).
Ich nutze dieses Prinzip in verschiedenen Projekten bereits seit einigen Jahren und ich erinnere mich mit einem dunklen Ergrauen an frühere Auslieferungsprozesse. Wer dies in Kundenprojekten lebt kann sich sodann glücklich zählen, da ein neues Release mit wenig personellen Aufwand und einem kühlen Köpfchen nur noch ein mechanischer Vorgang ist. Damit sind zum einen kurze Iterations- und Auslieferungszyklen und zum anderen schnelle Reaktionszeiten nach Behebung eines Fehlers möglich.

Veröffentlicht von

Sebastian

Als erfahrener Softwarentwickler entwickelt Sebastian in einer Softwareschmiede in Bonn Individualsoftware mit den Schwerpunkten in PHP und MySQL.

Er hat eine pfiffige Frau sowie drei quirlige Söhne, fährt gerne Auto und liebt handwerkliche Arbeiten die im häuslichen Umfeld so anfallen.

Schreibe einen Kommentar

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