Neuen Code live bereitstellen

29

Was ist die beste Vorgehensweise zum Bereitstellen von neuem Code auf einer Live-Site (E-Commerce)?

Im Moment habe ich Apache für +/- 10 Sekunden angehalten, als ich das Verzeichnis public_html_newin public_htmlund in alt umbenannt habe public_html_old. Dies führt zu einer kurzen Ausfallzeit, bevor ich Apache erneut starte.

Die gleiche Frage stellt sich, wenn Sie Git verwenden, um das neue Repo in das Live-Verzeichnis zu ziehen. Kann ich das Repo ziehen, während die Site aktiv ist? Und wie wäre es, wenn ich auch eine DB kopieren müsste?

Während der tar-Komprimierung (zu Sicherungszwecken) der Live-Site ist mir aufgefallen, dass Änderungen im Medienverzeichnis aufgetreten sind. Das zeigte mir, dass sich die Dateien regelmäßig ändern. Und wenn diese Änderungen stören können, wenn Apache während der Bereitstellung nicht gestoppt wird.

nicoX
quelle

Antworten:

13

Die Verwendung eines Lastenausgleichs ist eine gute Idee. Wenn die Site wichtig genug ist, um einige Sekunden Ausfallzeit zu befürchten, ist es wichtig genug, um Fehlertoleranz zu befürchten.

Abgesehen davon, wenn dies auf einem UNIX-System ist, können Sie Apache während des Umbenennens (oder Symlink-Updates usw.) zurückstellen:

killall -STOP httpd  # Pause all httpd processes
mv public_html public_html_orig
mv public_html_new public_html
killall -CONT httpd  # Resume all httpd processes

Dies verhindert, dass Apache während der Umbenennung neue Anforderungen akzeptiert. Wenn Sie Symlinks oder einen anderen Ansatz bevorzugen, können Sie dieselbe Idee verwenden:

killall -STOP httpd  # Pause all httpd processes
rm /var/www/html
ln -s /var/www/version/03 /var/www/html
killall -CONT httpd  # Resume all httpd processes

Beachten Sie, dass ausstehende Verbindungen oder Pakete im Betriebssystem in die Warteschlange gestellt werden. Erwägen Sie bei einer stark ausgelasteten Site, ListenBacklog entsprechend Ihrem httpd-Worker-Typ zu optimieren, und überprüfen Sie die Betriebssystemeinstellungen für das TCP-Listen-Backlog.

Sie können auch DocumentRoot in httpd.conf ändern und einen ordnungsgemäßen Neustart durchführen ( apachectl graceful). Der Nachteil hierbei ist das erhöhte Fehlerrisiko, da Sie auch jede DirectoryKonfiguration aktualisieren müssen .

GargantuChet
quelle
Wird die Site in der Pausensitzung weiterhin ausgeführt?
nicoX
4
Es gibt Apache keine CPU-Zeit mehr. Wenn Sie versucht haben, auf die Site in einem Browser zuzugreifen, während Apache angehalten ist, wartet der Browser auf die Verbindung, bis Apache wieder aufgenommen wird (oder der Browser läuft ab, wenn Apache länger als die Zeitüberschreitung angehalten wird). Wenn gerade jemand eine Datei herunterlädt, stoppt Apache das Senden von Daten, während diese angehalten werden, da keine CPU-Zeit benötigt wird. Auch dies führt nur dann zu Problemen, wenn Apache so lange angehalten wird, dass die Übertragung eine Zeitüberschreitung aufweist.
GargantuChet
5
Anders ausgedrückt: Die Site reagiert nicht, während Apache angehalten ist, ausstehende Vorgänge werden jedoch beendet, wenn sie fortgesetzt werden. Benutzer erhalten keine "Verbindung abgelehnt" und Downloads werden nicht unterbrochen, aber der Betrieb wird nur fortgesetzt, wenn Apache wieder aufgenommen wird. Auf diese Weise wird sichergestellt, dass vorhandene Transaktionen abgeschlossen werden können. Neue Anforderungen werden jedoch erst bearbeitet, nachdem Ihre neuen Inhalte platziert wurden.
GargantuChet
1
Bitte beachten Sie, dass dies in Websites mit hohem Datenaufkommen sehr leicht Ihren Apache-Service zum Erliegen bringen kann. 200 rq / s werden sehr leicht Ihren Verbindungspool zerstören, sobald Sie Ihren Apache-Prozess nach dem Umzug "entsperren" (wenn der Umzug eine Weile
dauert
1
Auf einer stark frequentierten Site müssen nach der Wiederaufnahme von Apache zahlreiche Anforderungen während des Flugs erledigt werden. Dadurch wird die Verarbeitung neuer Anforderungen gestaffelt. Dies ist auch ein gutes Argument, um sicherzustellen, dass Ihre Apache-Einstellungen (maximale Anzahl von Threads / Servern / Clients) angemessen sind, und um das TCP-Backlog entsprechend zu optimieren. Obwohl ich verwirrt bin, was Sie damit meinen, den Dienst zu "töten". Apache ist sehr gut einstellbar.
GargantuChet
32

Am schnellsten und einfachsten ist die Verwendung eines Versionsverzeichnisses wie

/var/www/version/01
/var/www/version/02

und benutze einen aktuellen symbolischen Link als html_root:

/var/www/html -> /var/www/version/02

Diese Technik lässt sich perfekt in ein Revisionskontrollsystem (svn, git, mercurial, ...) integrieren, da Sie Zweige und Tags auschecken, den symbolischen Link ändern und Apache neu laden können. Die Ausfallzeit ist minimal mit dieser Technik und ermöglicht ein sehr einfaches Rollback .

Es lässt sich auch gut mit komplexeren Bereitstellungssystemen wie RPM-Paketen oder der Infrastruktur zur Verwaltung von Konfigurationsänderungen (Chef, Marionette usw.) integrieren.

Wolkenweber
quelle
4
Einfachste Lösungen sind immer die besten ... :-) Natürlich darf nicht vergessen werden, dass einige FollowSymlinks und solche Apache Flags in den Configs benötigt werden.
Peter sagt, Monica
Achten Sie besonders darauf, was @PeterHorvath gesagt hat. Apache kann beim Arbeiten mit verknüpften DocumentRoots sehr mürrisch werden. Achten Sie darauf, sorgfältig zu testen!
mhutter
@mhutter Dank :-) Was wirklich problematisch ist , dass FollowSymlinks auf Apache ermöglicht Probleme der Sicherheit verursachen kann ...
sagt Peterh wieder einzusetzen Monica
Das Aktualisieren eines Symlinks ist keine atomare Operation. Auch ln -snfwenn Sie so etwas verwenden , um den ursprünglichen Symlink zu blockieren, ist die zugrunde liegende Operation ein unlinkund symlink. Es besteht die Möglichkeit, dass Benutzer während des Updates eine 404 erhalten. Dies ist nicht besser, als nur das ursprüngliche Verzeichnis aus dem Weg zu räumen und ein neues Verzeichnis umzubenennen (vorausgesetzt, Sie kreuzen nicht die Dateisysteme). Siehe die Antwort oben mit einem Häkchen daneben, das dieses Problem behebt.
GargantuChet
14

Das Umbenennen der Verzeichnisse ohne Herunterfahren von Apache sollte ebenfalls funktionieren. Das verkürzt das Fenster erheblich.mv public_html public_html_old && mv public_html_new public_htmlsollte in einem Bruchteil einer Sekunde fertig sein.

Ein paar Nachteile sind, dass dieser Ansatz 404jede Anfrage beantwortet, die noch während des Fensters ausgeführt werden kann. Und wenn Sie den obigen Befehl ausführen, ohne ein public_html_newVerzeichnis zu haben, schlägt dies fehl und Sie erhalten bei 404jeder Anfrage eine Website .

Es wird nicht unterstützt, es atomar mit Verzeichnissen zu tun. Aber Sie könnten es mit Symlinks tun. Anstatt ein Verzeichnis mit dem Namen zu public_htmlhaben, sollten Sie ein Verzeichnis mit dem Namen public_html.version-numberund einen Symlink haben, public_htmlder auf dieses Verzeichnis verweist. Nun können Sie ein Verzeichnis mit dem Namen public_html.new-version-numberund einen neuen Symlink mit dem Namen erstellen public_html.new.

Dann können Sie umbenennen , public_html.newum public_htmlatomar zu wechseln. Beachten Sie, dass dies mv"zu intelligent" ist, um diesen Umbenennungsvorgang durchzuführen. Sie können jedoch auch os.renamePython oder eine andere Methode verwenden, die den renameSystemaufruf aufruft, ohne zu versuchen, intelligent zu sein.

Was mit der Datenbank geschehen soll, hängt davon ab, welche Datenbank Sie verwenden und wofür Sie sie verwenden. Sie müssen viel mehr Details über die Datenbank bereitstellen, bevor wir Ihnen eine gute Antwort auf diesen Teil Ihrer Frage geben können.

Kasperd
quelle
1
Hat auf meinem Debian-System mveine -TOption, die verhindert, dass es dem Symlink folgt. So können Sie atomar umbenennen public_html.newüber public_html, vorausgesetzt , beide sind Soft - Links.
GargantuChet
11

Symlinks und mv sind Ihre Freunde. Wenn Sie jedoch wirklich vermeiden möchten, dass Endbenutzer beim Bereitstellen einer neuen Version eine Fehlerseite erhalten, sollten Sie einen Reverse-Proxy oder einen Load-Balancer vor mindestens 2 Back-End-Servern (Apache) haben in Ihrem Fall).

Während der Bereitstellung müssen Sie nur jeweils ein Backend stoppen, den neuen Code bereitstellen, neu starten und dann die verbleibenden Backends wiederholen.

Die Endbenutzer werden vom Proxy immer an gute Backends verwiesen.

Giovanni Toraldo
quelle
4
Ich habe gerade an dieser Antwort gearbeitet, als ich sah, dass Sie sie bereits gepostet haben. Balancer + 2-Server macht den Prozess unsichtbar und einfacher, nach einem schlechten Upgrade wiederherzustellen ...
Bart Silverstrim
9

Wenn Sie regelmäßig Änderungen an einem Produktionssystem vornehmen, kümmere ich mich um einen strukturierten Lebenszyklus. Eine gute Praxis ist Capistrano http://capistranorb.com/ . Dies ist eine Open Source-Lösung für die Bereitstellung von Software auf einem oder mehreren Servern auf mehreren Plattformen und Konfigurationen.

Für Magento gibt es sogar ein Plugin: https://github.com/augustash/capistrano-ash/wiki/Magento-Example

Für einzelne Server und fast nahtlose Übergänge empfehle ich die Verwendung von Symlinks.

Skiaddict
quelle
4

So mache ich es, indem ich meine Änderungen aus meiner lokalen Entwicklerumgebung in ein Online-Git-Repository wie Github übertrage. Meine Produktionsumgebung wird von einem Remote-Repository ausgeführt. Ich muss also nur ssh auf dem Server ausführen git pull, um die neuesten Änderungen zu speichern. Sie müssen Ihren Webserver nicht anhalten.

Wenn sich in Ihrem Projekt Dateien befinden, deren Einstellungen und / oder Inhalt von Ihrer lokalen Version abweichen (z. B. Konfigurationsdateien und Medien-Uploads), können Sie Umgebungsvariablen verwenden und / oder diese Dateien / Verzeichnisse zu einer .gitignoreDatei hinzufügen , um eine Synchronisierung mit dem Repository zu verhindern.

harryg
quelle
3

Meine erste Idee ist:

# deploy into public_html_new, and then:
rsync -vaH --delete public_html_new/ public_html/

Eine gute Lösung wäre die Verwendung von rsync. Es wurden nur die wirklich geänderten Dateien geändert. Achtung, die Schrägstriche am Ende der Pfade sind hier wichtig.

Normalerweise braucht Apache keinen Neustart, es ist nicht die Java-Welt. Es prüft auf Anfrage, ob jede PHP-Datei geändert wurde, und liest sie bei Änderungen automatisch neu (und tokenisiert sie erneut).

Git-Pull war ähnlich effizient, obwohl es etwas schwieriger war, Skripte zu schreiben. Selbstverständlich ermöglichte es ein breites Spektrum verschiedener Möglichkeiten zur Erkennung von Zusammenführungen / Änderungen.

Diese Lösung funktioniert nur dann reibungslos, wenn keine größeren Änderungen vorgenommen wurden. Bei großen Änderungen in der Bereitstellung kann ein gewisses Risiko nicht ausgeschlossen werden, da ein nicht zu vernachlässigendes Zeitintervall vorliegt, in dem der Code teilweise geändert wird und teilweise nicht.

Wenn es große Änderungen gibt, war mein Vorschlag Ihre ursprüngliche Lösung (zwei Umbenennungen).


Hier ist ein bisschen hardcore, aber 100% atomare Lösung:

(1) mounten Sie einen Teil Ihres Dateisystems, in dem Ihr Magento stattfindet:

mount /dev/sdXY /mnt/tmp

(2) --bindmounten Sie public_html_new in public_html:

mount --bind /path/to/public_html_new /path/to/public_html

Ab diesem Zeitpunkt sieht der Apache Ihre neue Bereitstellung. Eine Änderung eines 404 ist nicht möglich.

(3) Führen Sie die Synchronisation mit rsync durch, aber auf dem alternativen Mount-Punkt):

rsync -vaH --delete /mnt/tmp/path/to/public_html_new/ /mnt/tmp/path/to/public_html/

(4) Entfernen Sie die Bindehalterung

umount /path/to/public_html
sagt Peter, stell Monica wieder her
quelle
Wird der Befehl public_html löschen und public_html_new darin implementieren?
nicoX
@nicoX Nein, es werden nur die Änderungen kopiert .
Peter sagt, Monica
@nicoX Es durchläuft beide Verzeichnisstrukturen und wenn es einen Unterschied findet (neue Datei, geänderte Datei, gelöschte Datei), ändert es das zweite Verzeichnis so, dass es dem ersten entspricht, wie es benötigt wird. Das Ergebnis, wenn Sie public_html gelöscht und dann public_html_new an seinen Platz verschoben haben, jedoch ohne die Möglichkeit eines temporären 404-Problems.
Peter sagt, Monica
1
Nein, das ist keine gute Idee. Abhängig von den Änderungen haben Sie möglicherweise eine kurze Zeitspanne, in der sich der Code public_htmlin einem inkonsistenten Zustand befindet, und Sie möchten dieses Risiko nicht eingehen.
Sven
@SvW Du hast recht, meine Idee ist nur in Ordnung, wenn es nur geringfügige Änderungen gibt. Ich habe meine Antwort entsprechend erweitert.
Peter sagt, Monica
1

Verschieben / Ersetzen des http_publicOrdners kann mit einfach mvoder erreicht werdenln -s Befehle oder gleichwertig , während der HTTP - Server laufen hält. Sie können Skripte ausführen, um die Ausfallzeit erheblich zu verringern. Überprüfen Sie jedoch sorgfältig die Rückkehrcodes Ihrer Befehle im Skript, wenn Sie den Prozess automatisieren.

Wenn Sie jedoch keine Ausfallzeiten erzielen möchten, muss diese auch von Ihrer Anwendung unterstützt werden. Die meisten Anwendungen verwenden eine Datenbank, um die Persistenz zu gewährleisten. Wenn Version N Ihrer Anwendung mit Version N + 1 (oder der Rückseite) Ihres Datenmodells in Konflikt gerät, kann dies zu Problemen führen, wenn das Entwicklungsteam dies nicht vorhersieht.

Erfahrungsgemäß ist die Aufrechterhaltung einer solchen Konsistenz durch Upgrades für die meisten Anwendungen nicht selbstverständlich. Ein ordnungsgemäßes Herunterfahren ist trotz der Ausfallzeit ein guter Weg, um Konsistenzprobleme zu vermeiden.

Uriel
quelle