137 Stimmen

Wie man eine ASP.NET-Anwendung ohne Ausfallzeiten bereitstellt

Um eine neue Version unserer Website bereitzustellen, gehen wir wie folgt vor:

  1. Zipen Sie den neuen Code und laden Sie ihn auf den Server hoch.
  2. Löschen Sie auf dem Live-Server den gesamten Live-Code aus dem IIS-Website-Verzeichnis.
  3. Entpacken Sie die neue Code-Zipdatei in das nun leere IIS-Verzeichnis

Dieser Vorgang ist skriptgesteuert und geht recht schnell vonstatten, dennoch kann es zu einer Ausfallzeit von 10-20 Sekunden kommen, wenn die alten Dateien gelöscht und die neuen Dateien bereitgestellt werden.

Gibt es Vorschläge für eine Methode mit 0 Sekunden Ausfallzeit?

0 Stimmen

Sollte das nicht auf ServerFault stehen?

53 Stimmen

Vielleicht, aber ServerFault gab es im September '08 noch nicht.

3 Stimmen

Kann IIS auf einen Symlink-Ordner verweisen? Wird das Ändern des Symlinks dazu führen, dass der IIS-Prozess recycelt wird?

7voto

Jack Punkte 4364

Mit der Klasse ServerManager von Microsoft.Web.Administration können Sie Ihren eigenen Verteilungsagenten entwickeln.

Der Trick besteht darin, den PhysicalPath des VirtualDirectory zu ändern, was zu einem atomaren Online-Wechsel zwischen alten und neuen Webanwendungen führt.

Beachten Sie, dass dies dazu führen kann, dass alte und neue AppDomains parallel ausgeführt werden!

Das Problem besteht darin, wie Änderungen an Datenbanken usw. synchronisiert werden können.

Durch die Abfrage nach dem Vorhandensein von AppDomains mit alten oder neuen PhysicalPaths kann festgestellt werden, wann die alte(n) AppDomain(s) beendet und die neue(n) AppDomain(s) gestartet wurden.

Um den Start einer AppDomain zu erzwingen, müssen Sie eine HTTP-Anfrage stellen (IIS 7.5 unterstützt die Autostart-Funktion)

Jetzt brauchen Sie eine Möglichkeit, Anfragen für die neue AppDomain zu blockieren. Ich verwende eine benannte Mutex, die vom Deployment Agent erstellt und verwaltet wird, auf die der Application_Start der neuen Web-App wartet und die dann vom Deployment Agent freigegeben wird, sobald die Datenbankaktualisierungen durchgeführt wurden.

(Ich verwende eine Markierungsdatei in der Webanwendung, um das Mutex-Warteverhalten zu aktivieren) Sobald die neue Webanwendung ausgeführt wird, lösche ich die Markierungsdatei.

5voto

Sam Meldrum Punkte 13529

Die einzigen Methoden ohne Ausfallzeiten, die mir einfallen, beinhalten das Hosting auf mindestens 2 Servern.

1voto

RickNZ Punkte 18158

Ich würde Georges Antwort für einen einzelnen Server wie folgt verfeinern:

  1. Verwenden Sie ein Web Deployment Project, um die Site in eine einzige DLL zu kompilieren.
  2. Komprimieren Sie die neue Website, und laden Sie sie auf den Server hoch.
  3. Entpacken Sie sie in einen neuen Ordner, der sich in einem Ordner mit den richtigen Berechtigungen für die Website befindet, so dass die entpackten Dateien die Berechtigungen korrekt erben (vielleicht e: \web mit den Unterordnern v20090901, v20090916, usw.)
  4. Verwenden Sie den IIS-Manager, um den Namen des Ordners zu ändern, der die Site enthält
  5. Behalten Sie den alten Ordner noch eine Weile, damit Sie bei Problemen auf ihn zurückgreifen können

Schritt 4 führt dazu, dass der IIS-Arbeitsprozess recycelt wird.

Dies bedeutet nur dann keine Ausfallzeit, wenn Sie keine InProc-Sitzungen verwenden; verwenden Sie stattdessen den SQL-Modus, wenn Sie können (noch besser, vermeiden Sie den Sitzungsstatus ganz).

Natürlich ist es ein wenig komplizierter, wenn es mehrere Server und/oder Datenbankänderungen gibt....

1 Stimmen

Gleiches Problem wie @Sklivvz -- Diese Methode stürzt ab, sobald die Code-Rolle strukturelle Änderungen an der Datenbank hat.

4 Stimmen

Deshalb sagte ich, dass es bei DB-Änderungen komplizierter ist... Das Ausrollen von Code mit strukturellen Änderungen an der DB ist nicht nur eine Frage der Bereitstellung; es muss auch Unterstützung im Code und wahrscheinlich auch in der DB geben.

1voto

gliljas Punkte 715

Um die Antwort von sklivvz zu ergänzen, die sich auf eine Art Load Balancer (oder einfach eine Standby-Kopie auf demselben Server) stützt

  1. Leiten Sie den gesamten Datenverkehr zu Site/Server 2
  2. Optional eine Weile warten, um sicherzustellen, dass möglichst wenige Benutzer ausstehende Workflows für die bereitgestellte Version haben
  3. Stellen Sie Site/Server 1 bereit und wärmen Sie ihn so weit wie möglich auf.
  4. Datenbankmigrationen transaktional durchführen (dies zu ermöglichen ist anzustreben)
  5. Leiten Sie sofort den gesamten Datenverkehr zum Standort/Server 1
  6. Bereitstellung auf Standort/Server 2
  7. Direkter Verkehr zu beiden Websites/Servern

Es ist möglich, ein wenig Smoke-Testing einzuführen, indem man einen Datenbank-Snapshot/eine Datenbank-Kopie erstellt, aber das ist nicht immer machbar.

Falls möglich und erforderlich, verwenden Sie "Routing-Unterschiede", wie z. B. unterschiedliche Tenant-URLs (customerX.myapp.net) oder unterschiedliche Benutzer, um die Anwendung zunächst an eine unwissende Gruppe von Versuchskaninchen zu verteilen. Wenn alles klappt, geben Sie die Anwendung für alle frei.

Da es sich um Datenbankmigrationen handelt, ist es oft unmöglich, zu einer früheren Version zurückzukehren.

Es gibt Möglichkeiten, Anwendungen in solchen Szenarien zu verbessern, z. B. durch die Verwendung von Ereigniswarteschlangen und Wiedergabemechanismen, aber da es hier um die Bereitstellung von Änderungen an etwas geht, das bereits in Gebrauch ist, gibt es keinen wirklich sicheren Weg.

1voto

Stefan Steiger Punkte 72861

So mache ich es:

Absolute Mindestanforderungen an das System:
1 Server mit

  • 1 Load Balancer/Reverse Proxy (z. B. nginx), der auf Port 80 läuft
  • 2 ASP.NET-Core/mono reverse-proxy/fastcgi chroot-jails oder docker-containers, die auf 2 verschiedenen TCP-Ports lauschen
    (oder auch nur zwei Reverse-Proxy-Anwendungen auf 2 verschiedenen TCP-Ports ohne Sandbox)

Arbeitsablauf:

Transaktion myupdate starten

try
    Web-Service: Tell all applications on all web-servers to go into primary read-only mode 
    Application switch to primary read-only mode, and responds 
    Web sockets begin notifying all clients 
    Wait for all applications to respond

    wait (custom short interval)

    Web-Service: Tell all applications on all web-servers to go into secondary read-only mode 
    Application switch to secondary read-only mode (data-entry fuse)
    Updatedb - secondary read-only mode (switches database to read-only)

    Web-Service: Create backup of database 
    Web-Service: Restore backup to new database
    Web-Service: Update new database with new schema 

    Deploy new application to apt-repository 
    (for windows, you will have to write your own custom deployment web-service)
    ssh into every machine in array_of_new_webapps
    run apt-get update
    then either 
    apt-get dist-upgrade
    OR
    apt-get install <packagename>
    OR 
    apt-get install --only-upgrade <packagename>
    depending on what you need
    -- This deploys the new application to all new chroots (or servers/VMs)

    Test: Test new application under test.domain.xxx
    -- everything that fails should throw an exception here
    commit myupdate;

    Web-Service: Tell all applications to send web-socket request to reload the pages to all clients at time x (+/- random number)
    @client: notify of reload and that this causes loss of unsafed data, with option to abort 

    @ time x:  Switch load balancer from array_of_old_webapps to array_of_new_webapps 
    Decomission/Recycle array_of_old_webapps, etc.

catch
        rollback myupdate 
        switch to read-write mode
        Web-Service: Tell all applications to send web-socket request to unblock read-only mode
end try

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X