Frage Bereitstellen von neuem Code live


Wie empfiehlt es sich, neuen Code auf einer Live-Site (E-Commerce) bereitzustellen?

Für den Moment habe ich Apache für +/- 10 Sekunden beim Umbenennen des Verzeichnisses gestoppt public_html_new zu public_html und alt zu public_html_old. Das schafft eine kurze Ausfallzeit, bevor ich Apache wieder starte.

Die gleiche Frage gilt, wenn Sie Git verwenden, um den neuen 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 (Backup-Zweck) Komprimierung der Live-Site habe ich bemerkt, dass Änderungen im Media-Verzeichnis aufgetreten sind. Das hat mir gezeigt, dass sich Dateien regelmäßig ändern. Und wenn diese Änderungen stören können, wenn Apache während der Bereitstellung nicht gestoppt wird.


28
2017-08-12 12:08


Ursprung




Antworten:


Die Verwendung eines Lastenausgleichs ist eine gute Idee. Wenn die Site wichtig genug ist, um sich über ein paar Sekunden Ausfallzeit Gedanken zu machen, ist es wichtig, sich um Fehlertoleranz zu kümmern.

Wenn dies auf einem UNIX-System geschieht, können Sie Apache während des Umbenennens (oder Symlink-Updates usw.) in die Warteschleife setzen:

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 des Umbenennens neue Anfragen akzeptiert. Wenn Sie Symlinks oder einen anderen Ansatz bevorzugen, kann die gleiche Idee verwendet werden:

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 alle ausstehenden Verbindungen oder Pakete in das Betriebssystem eingereiht werden. Wenn Sie eine stark frequentierte Site verwenden, sollten Sie ListenBacklog optimieren, wenn dies für Ihren httpd-Arbeitertyp angemessen ist, und Ihre Betriebssystemeinstellungen für TCP-Listen-Backlog überprüfen.

Sie könnten DocumentRoot auch in httpd.conf ändern und einen grazilen Neustart durchführen (apachectl graceful). Der Nachteil hier ist das erhöhte Risiko von Fehlern, da Sie alle aktualisieren müssen Directory Konfiguration auch.


13
2017-08-14 14:53



Wird die Pausensitzung die Site weiterhin ausführen? - nicoX
Es gibt Apache keine CPU-Zeit mehr. Wenn Sie versucht haben, während eines Apache-Stopps auf die Site in einem Browser zuzugreifen, wartet der Browser auf die Verbindung, bis der Apache-Vorgang fortgesetzt wird (oder der Zeitlimit des Browsers überschritten wird, wenn der Apache länger als die Zeitüberschreitung pausiert). Wenn jemand gerade eine Datei herunterlädt, sendet Apache während des Pausens keine weiteren Daten mehr, da er keine CPU-Zeit benötigt. Auch dies wird nur Probleme verursachen, wenn Apache so lange gestoppt wird, dass die Übertragung abläuft. - GargantuChet
Anders gesagt, die Site reagiert nicht, während Apache pausiert ist. Ausstehende Vorgänge werden jedoch beendet, wenn sie fortgesetzt werden. Benutzer erhalten keine "Verbindung abgelehnt", und Downloads werden nicht unterbrochen, aber Operationen werden nur fortgesetzt, wenn Apache wieder aufgenommen wird. Dadurch wird sichergestellt, dass vorhandene Transaktionen abgeschlossen werden können. Neue Anforderungen werden jedoch erst bearbeitet, nachdem der neue Inhalt in den richtigen Platz verschoben wurde. - GargantuChet
Bitte beachten Sie, dass dies bei jeder Website mit hohem Traffic-Aufkommen den Apache-Service sehr leicht zum Erliegen bringen kann. 200 rq / s werden Ihren Verbindungspool sehr leicht zerstören, sobald Sie Ihren Apache-Prozess nach dem Umzug 'entsperren' (wenn der Umzug eine Weile dauert) - CloudWeavers
Auf einer stark frequentierten Site wird es viele In-Flight-Anfragen geben, die beendet werden müssen, wenn Apache wieder aufgenommen wird. Dies wird die Verarbeitung neuer Anfragen staffeln. Es ist auch ein gutes Argument, um sicherzustellen, dass Ihre Apache-Einstellungen (maximale Anzahl von Threads / Servern / Clients) vernünftig sind, und das TCP-Backlog entsprechend anzupassen. Obwohl ich verwirrt bin über das, was du meinst, indem du den Dienst "tötest". Apache ist sehr abstimmbar. - GargantuChet


Am schnellsten und einfachsten ist es, ein Versionsverzeichnis wie

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

und verwende einen aktuellen symbolischen Link als dein html_root:

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

Diese Technik integriert sich perfekt in eine Versionskontrollsystem (svn, git, mercurial, ...) wie Sie Filialen & Tags auschecken können, ändert den symbolischen Link und lädt Apache neu. Das Ausfallzeiten sind minimal mit dieser Technik und es ermöglicht sehr einfaches Rollback.

Es kann auch gut mit komplexeren Bereitstellungssystemen wie RPM-Paketen oder Konfigurations-Change-Management-Infrastruktur (Küchenchef, Puppet usw.) integriert werden.


32
2017-08-12 13:26



Einfachste Lösung ist immer die beste ... :-) Vergessen Sie natürlich nicht zu erwähnen, dass einige FollowSymlinks und solche Apache Flags in den Configs benötigt werden. - peterh
Achte besonders darauf, was @PeterHorvath gesagt hat. Apache kann sehr mürrisch werden, wenn er mit symbolisierten DocumentRoots arbeitet. Seien Sie sicher, sorgfältig zu prüfen! - mhutter
@mhutter Danke :-) Was wirklich problematisch ist, ist das Aktivieren von FollowSymlinks auf Apache kann Sicherheitsprobleme verursachen ... - peterh
Das Aktualisieren eines Symlinks ist keine atomare Operation. Selbst mit etwas wie ln -snf Um den ursprünglichen Symlink zu überlisten, ist die zugrunde liegende Operation ein unlink und symlink. Es besteht die Möglichkeit, dass Benutzer während des Updates einen 404 erhalten. Dies ist nicht besser, als nur das ursprüngliche Verzeichnis aus dem Weg zu räumen und ein neues in den Platz umzubenennen (vorausgesetzt, Sie überschreiten keine Dateisysteme). Siehe die Antwort oben mit einem Häkchen daneben, das dieses Problem anspricht. - GargantuChet


Das Umbenennen der Verzeichnisse, ohne Apache herunterzufahren, sollte ebenfalls funktionieren. Das wird das Fenster deutlich verkürzen. mv public_html public_html_old && mv public_html_new public_html sollte in einem Bruchteil einer Sekunde enden.

Ein paar Nachteile sind, dass dieser Ansatz eine geben wird 404 auf irgendeine Anfrage, die noch während des Fensters passiert. Und wenn Sie den obigen Befehl ausführen, ohne a public_html_new Verzeichnis wird es fehlschlagen und Sie mit einer Website geben lassen 404 auf jede Anfrage.

Dies wird atomar mit Verzeichnissen nicht unterstützt. Aber du könntest es mit Symlinks machen. Anstatt ein Verzeichnis namens zu haben public_html, habe ein Verzeichnis namens public_html.version-number und ein Symlink namens public_html auf dieses Verzeichnis zeigen. Jetzt können Sie ein Verzeichnis namens erstellen public_html.new-version-number und ein neuer Symlink namens public_html.new.

Dann können Sie umbenennen public_html.new zu public_html atomar schalten. Beachte das mv ist "zu intelligent", um das Umbenennen durchzuführen, aber es könnte mit verwendet werden os.rename von Python oder irgendetwas anderem, das die rename Systemanruf ohne zu versuchen, intelligent zu sein.

Was mit der Datenbank zu tun ist, hängt davon ab, welche Datenbank Sie verwenden und wofür Sie sie verwenden. Sie müssen viel mehr Details zur Datenbank angeben, bevor wir Ihnen eine gute Antwort auf diesen Teil Ihrer Frage geben können.


14
2017-08-12 12:38



Auf meinem Debian-System mv hat ein -T Option, die verhindert, dass sie dem Symlink folgt. Dadurch können Sie sich automatisch umbenennen public_html.new Über public_htmlunter der Annahme, dass beide weiche Links sind. - GargantuChet


Symlinks und mv sind Ihre Freunde. Wenn Sie jedoch wirklich vermeiden müssen, dass Endbenutzer eine Fehlerseite erhalten, während Sie eine neue Version bereitstellen, sollten Sie einen Reverse-Proxy oder einen Load-Balancer vor mindestens zwei Backend-Servern (Apache) haben in Ihrem Fall).

Während der Bereitstellung müssen Sie nur jeweils ein Back-End stoppen, den neuen Code bereitstellen, neu starten und dann die verbleibenden Back-Ends durchlaufen.

Die Endbenutzer werden vom Proxy immer zu guten Back-Ends geleitet.


11
2017-08-12 17:29



Ich habe gerade an dieser Antwort gearbeitet, als ich sah, dass du es schon gepostet hast. Balancer + 2 Server macht den Prozess unsichtbar und einfacher von einem schlechten Upgrade zu erholen ... - Bart Silverstrim


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

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

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


9
2017-08-12 12:57





Die Art, wie ich es mache, besteht darin, meine Änderungen von meiner lokalen Entwicklungsumgebung in ein Online-Git-Repository wie Github zu übertragen. Meine Produktionsumgebung wird von einem Remote-Repository ausgeführt, so dass ich nur ssh auf dem Server ausführen und ausführen muss git pull um die letzten Änderungen zu reduzieren. Sie müssen Ihren Webserver nicht stoppen.

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


4
2017-08-12 14:59





Meine erste Idee ist:

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

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

Normalerweise braucht Apache keinen Neustart, es ist nicht die Java-Welt. Es überprüft auf Anfrage die Änderung jeder php-Datei und liest die Änderungen automatisch neu (und weist sie erneut in Token auf).

Git Pull war ähnlich effizient, obwohl es ein bisschen schwieriger zu schreiben war. Natürlich ermöglichte es ein breites Spektrum an verschiedenen Möglichkeiten zum Zusammenführen / Ändern von Daten.

Diese Lösung wird nur dann nahtlos funktionieren, wenn es keine wirklich großen Änderungen gibt - wenn es große Änderungen in der Bereitstellung gibt, kann ein kleines Risiko nicht ausgeschlossen werden, da es einen nicht vernachlässigbaren Zeitraum gibt, wenn der Code teilweise geändert wird und teilweise nicht.

Wenn es große Änderungen gibt, war mein Vorschlag Ihre erste Lösung (zwei Umbenennen).


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

(1) Mach ein alternatives mount etwas von deinem Dateisystem, wo dein Magento stattfindet:

mount /dev/sdXY /mnt/tmp

(2) a --bind mount von public_html_new in public_html:

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

Ab diesem Zeitpunkt wird der Apache Ihre neue Bereitstellung sehen. Jede Änderung eines 404 ist unmöglich.

(3) mach die Synchronisation mit rsync, aber auf dem alternativen Einhängepunkt):

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

(4) Entferne das Bind-Mount

umount /path/to/public_html

3
2017-08-12 12:20



Löscht der Befehl public_html und publish public_html_new? - nicoX
@nicoX Nein, es wird kopiert nur die Änderungen. - peterh
@nicoX Es geht weiter beide Verzeichnisstrukturen, und wenn es einen Unterschied findet (neue Datei, geänderte Datei, gelöschte Datei), ändert es das zweite Verzeichnis so, dass es mit dem ersten übereinstimmt, wie es benötigt wird. Das Ergebnis, wenn Sie public_html gelöscht und dann public_html_new an seinen Platz verschoben haben, aber ohne die Möglichkeit eines vorübergehenden 404-Problems. - peterh
Nein, das ist keine gute Idee. Abhängig von den Änderungen haben Sie möglicherweise eine kurze Zeit, in der der Code eingegeben wurde public_html ist in einem inkonsistenten Zustand, und Sie wollen diese Chance nicht nutzen. - Sven♦
@SvW Du hast recht, meine Idee ist nur in Ordnung, wenn es nur geringfügige Änderungen gibt. Ich habe meine Antwort entsprechend erweitert. - peterh


Verschieben / Ersetzen der http_public Ordner kann mit einfachen erreicht werden mv oder ln -s Befehle oder gleichwertig, während Ihr http-Server weiterläuft. Sie können einige Skripts ausführen, um die Ausfallzeit erheblich zu reduzieren. Überprüfen Sie jedoch sorgfältig die Rückgabewerte Ihrer Befehle im Skript, wenn Sie den Prozess automatisieren.

Das heißt, wenn Sie keine Ausfallzeiten erreichen wollen, Sie Anwendung muss es auch unterstützen. Die meisten Anwendungen verwenden eine Datenbank für Persistenz. Wenn Sie die Version N Ihrer Anwendung mit der Version N + 1 (oder der Rückseite) Ihres Datenmodells verwechseln, kann dies zu Problemen führen, wenn das Entwicklungsteam dies nicht vorhersieht.

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


1
2017-08-17 12:52