Aktualisieren einer Web-App ohne Ausfallzeiten

31

Es ist eine PHP-App. Wie kann ich die Ausfallzeit minimieren, während ich die gesamte Codebasis aktualisiere?

Simon Hayter
quelle

Antworten:

44

Was wir im Allgemeinen bei der Arbeit tun, ist:

  • Vor der Aktualisierung lautet der Dokumentenstamm des Servers:
    • im /www/app-2009-09-01
    • Der Zugriff erfolgt jedoch über einen symbolischen Link, genannt /www/application
  • Wir setzen die gesamte neue Codebasis auf /www/app-2009-09-08
  • Sobald die gesamte Codebasis vorhanden ist:
    • Wir entfernen den alten symbolischen Link
    • Wir erstellen einen neuen symbolischen Link, der immer noch aufgerufen wird /www/application, aber auf die neuen Quellen verweist:/www/app-2009-09-08
  • Wir laden Apache neu, um die Berücksichtigung der Änderung zu erzwingen.

All dies geschieht über ein automatisches Skript (das einzige, was nicht automatisch geschieht, ist, dass wir es bei Bedarf starten). Das heisst :

  • Alles geht schnell (besonders das Schalten der symbolischen Verbindung, was der wichtige Teil ist)
  • Kein Risiko, einen Fehler zu machen: Das Skript ist gut getestet und funktioniert seit Monaten / Jahren


Ein weiterer Vorteil dieser symbolischen Verknüpfungsvorgehensweise besteht darin, dass es sehr einfach ist, ein Update zurückzusetzen, wenn wir einen katastrophalen Fehler erst feststellen, nachdem wir die neue Version der Quellen in Betrieb genommen haben: Wir müssen nur die symbolischen Verknüpfungen zurücksetzen.

Das hindert Sie natürlich nicht daran, die neue Version auf Ihrem Staging-Server zu testen, bevor Sie sie in Betrieb nehmen - aber wer weiß ... Manchmal gibt es einen wirklich großen Fehler, den niemand gesehen hat testing :-(
Zum Beispiel, weil es auf dem Staging-Rechner keine regelmäßigen Lasttests gibt.
(Ich habe gesehen, dass das "Rollback" -Ding in 3 Jahren 4 oder 5 Mal verwendet wurde - jedes Mal den tag gerettet - und die websites ^^)


Hier ist ein kurzes Beispiel: Angenommen, ich habe diesen VirtualHost in meiner Apache-Konfiguration:

<VirtualHost *>
        ServerName example.com
        DocumentRoot /www/application
        <Directory /www/application>
            # Whatever you might need here (this example is copy-pasted from a test server and test application ^^ )
            Options Indexes FollowSymLinks MultiViews +SymLinksIfOwnerMatch
            AllowOverride All
            php_value   error_reporting 6135
            php_value short_open_tag  on
        </Directory>
</VirtualHost>

Ziemlich "Standard" ... Das einzige, was ist, /www/applicationist kein richtiges Verzeichnis: Es ist nur ein symbolischer Link zur aktuellen Version der Quellen.
Das heißt, wenn Sie die Quellen auf den Server gestellt, aber noch nicht gewechselt haben, haben Sie ungefähr Folgendes:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:08 application -> /www/app-2009-09-01

Beachten Sie, dass das Symbol auf die "alte Version" verweist

Nachdem die neue Version vollständig auf den Server hochgeladen wurde, wechseln wir:

root@shark:/www
# rm /www/application
root@shark:/www
# ln -s /www/app-2009-09-08 /www/application

Und nun die /www/applicationPunkte zur neuen Version der Quellen:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:09 application -> /www/app-2009-09-08

Und wir müssen nur Apache neu starten:

root@shark:/www
# /etc/init.d/apache2 restart
 * Restarting web server apache2

Die drei Schritte " Entfernen der Verknüpfung; Erstellen der neuen Verknüpfung; Neustarten von Apache " sollten schnell ausgeführt werden. dh durch ein automatisiertes Skript und nicht durch einen Menschen.

Verwendung dieser Lösung:

  • Sie können so viel Zeit in Anspruch nehmen, wie Sie zum Hochladen der neuen Version der Quellen benötigen: Apache verwendet sie nicht, solange das Symlic nicht geändert wurde
  • Wenn alles in Ordnung ist, wechseln Sie einfach den Symlink: Es geht schneller als das Ändern von 1 oder 2 Dateien ... Das bedeutet praktisch keine Ausfallzeit :-)

Und wenn Sie einen Opcode-Cache wie APC mit der Option stat bei 0 verwenden, kann dies vermutlich sogar zu einem noch geringeren Ausfallrisiko führen.


Dies ist natürlich die "einfache" Version - wenn Sie zum Beispiel einige hochgeladene Dateien haben, müssen Sie irgendwo einen anderen Symlink oder einen anderen VirtualHost oder was auch immer verwenden ...


Hoffe das ist klarer :-)

Pascal MARTIN
quelle
Es ist auch eine Art Serveraustausch. :-)
Wim ten Brink
mod_rewrite um symbolische links zu verwalten?
@gAMBOOKa: nein: nur eine Frage von Apaches DocumentRoot (oder VirtualHost DocumentRoot), die / www / application ist ;; dh die symbolische Verbindung - egal wohin diese verweist.
2
Tolle Antwort. Noch ein Tipp: Sie können die symbolische Verknüpfung herstellen, ohne die Verknüpfung zu lösen. Wie gesagt: "Die drei Schritte ... sollten schnell erledigt werden, dh durch ein automatisiertes Skript und nicht durch einen Menschen." Der Befehl mv ist eine atomare Operation. Sie können also einen Symlink wie 'ln -s / www / app-2011-01-28 / www / application-temp' erstellen und dann einen Befehl 'mv -T / www / application-temp' ausführen / www / application '.
1
Es gibt etwas, das von der Symlink-Methode nicht abgedeckt wurde. Ihr Weg funktioniert mit Apache + mod_php, aber es könnte auf lighttpd + fastcgi fehlschlagen. In einer stark frequentierten Website wird die Anfrage während des Austauschs des Links bearbeitet, bei dem die Abhängigkeit des PHP-Codes bei einer gemischten Version fehlschlägt.
Dennis C
2

Können Sie den vorhandenen Code nicht nehmen und das Projekt in eine separate Test-PHP-Datei migrieren und diese verwenden, während Sie Ihre Updates vornehmen? Ich meine, Sie sollten einen Testserver und einen Produktionsserver haben, damit Sie keine Ausfallzeiten haben, wenn Sie ein Update durchführen müssen.

Gemeinschaft
quelle
1

Richten Sie einen zweiten Server mit der aktualisierten Codebasis ein und wechseln Sie diese so schnell wie möglich. :-)

Wenn dies nicht möglich ist, stellen Sie sicher, dass Ihre Codebasis in Dutzende kleinerer Teile unterteilt ist. Dann wäre die Ausfallzeit auf jeweils nur einen Unterbereich begrenzt. Die kleineren Codeblöcke lassen sich leichter austauschen und die meisten funktionieren problemlos weiter. Probieren Sie dies jedoch zunächst in einer Testumgebung aus!

Wim ten Brink
quelle
Da die App nicht mit fragmentierten Modulen getestet wurde, kann es zu unerwarteten Szenarien kommen.
Dies bedeutet, dass dies nach diesem Update auf Ihrer ToDo-Liste steht. :-) Machen Sie es modularer und Sie können pro Modul aktualisieren.
Wim ten Brink
1
Das steht auf der ToDo-Liste, ist aber ein langfristiges Ziel. Wir sind ein junges Startup, daher wird die Organisation innerhalb des Entwicklerteams natürlich eine Weile dauern. = D
1

Zunächst einmal verwende und mag ich oft eine Methode, die der von Pascal MARTIN ähnelt.

Eine andere Methode, die ich auch mag, ist mein SCM zu verwenden, um neuen Code zu pushen. Der genaue Prozess hängt von Ihrem SCM-Typ ab (git vs svn vs ...). Wenn Sie svn verwenden, möchte ich einen "Online" - oder "Produktions" -Zweig erstellen, den ich als Dokumentstamm auf dem Server auschecke. Wann immer ich neuen Code von einem anderen Zweig / Tag / Trunk übertragen möchte, gebe ich den neuen Code einfach in den "Online" -Zweig ein und führe svn update im Dokumentenstamm aus. Dies ermöglicht sehr einfache Rollbacks, da ein vollständiges Revisionsprotokoll darüber vorhanden ist, was auf dem Server hoch- / runtergelaufen ist und wer es wann getan hat. Sie können diesen "Online" -Zweig auch ganz einfach auf einer Testbox ausführen, um die App zu überprüfen, die Sie pushen möchten.

Der Prozess ist für Git und andere SCM-Stile ähnlich, wurde jedoch so modifiziert, dass er natürlicher für die Art des Workflows ist.

Möchten Sie Aktualisierungen abrufen oder abrufen, anstatt sie zu übertragen? Haben Sie einfach einen Cron Job oder einen anderen, intelligenteren Mechanismus, mit dem svn update automatisch ausgeführt wird.

Extra: Sie können diesen Prozess auch zum Sichern von Dateien verwenden, die Ihre Anwendung auf die Festplatte geschrieben hat. Lassen Sie einfach einen Cron-Job oder einen anderen Mechanismus svn commit ausführen. Jetzt werden die Dateien, die Ihre Anwendung erstellt hat, in Ihrem SCM gesichert, die Revision wird protokolliert usw. (Wenn beispielsweise ein Benutzer eine Datei auf der Festplatte aktualisiert, aber Sie möchten, dass Sie sie zurücksetzen, drücken Sie einfach die alte Revision).


quelle
0

Ähnlich gehe ich auch bei Pascal MARTIN vor. Anstatt jedoch mehrere Versionen meiner App auf den Produktionsserver hochzuladen, behalte ich die "Builds" hinter meiner Firewall in einem separaten Verzeichnis mit Build-Nummer und Datum. Wenn ich eine neue Version hochladen möchte, verwende ich ein einfaches Skript, das "rsync -avh --delay-updates" enthält. Mit dem Flag "delay = updates" wird alles (was anders ist) in einen temporären Ordner hochgeladen, bis alle Updates vorhanden sind. Anschließend wird am Ende der Übertragung alles auf einmal auf die richtigen Pfade verschoben, sodass sich die App niemals in einem befindet halb alter halb neuer Zustand. Dies hat den gleichen Effekt wie die oben beschriebene Methode, außer dass ich nur eine Version der App auf dem Produktionsstandort behalte (am besten nur die wichtigsten Dateien auf dem Produktionsserver, IMO).


quelle