Frage

Wenn Sie eine große Java Webapp Bereitstellung (> 100 MB .war) Ich verwende derzeit die folgenden Bereitstellungsprozess:

  • Die Anwendung IST-Datei auf dem Entwicklungscomputer lokal erweitert wird.
  • Die erweiterte Anwendung ist rsync: ed aus der Entwicklungsmaschine in die Live-Umgebung
  • .
  • Der App-Server in der Live-Umgebung nach dem rsync neu gestartet. Dieser Schritt ist nicht unbedingt notwendig, aber ich habe die Server-Neustart der Anwendung auf Deployment gefunden vermeidet „java.lang.OutOfMemoryError: PermGen Raum“. Aufgrund des häufigen Klasse Ladens

Gute Dinge über diesen Ansatz:

  • Die rsync minimiert die Menge an Daten aus der Entwicklungsmaschine in die Live-Umgebung gesendet. die gesamte WAR-Datei Hochladen dauert über 10 Minuten, während ein rsync ein paar Sekunden dauert.

Bad Dinge über diesen Ansatz:

  • Während die rsync läuft der Anwendungskontext, da die Dateien aktualisiert werden neu gestartet wird. Im Idealfall sollte der Neustart geschehen, nachdem der rsync abgeschlossen ist, nicht, wenn es noch ausgeführt wird.
  • Die App Server-Neustart verursacht etwa zwei Minuten Ausfallzeit.

Ich mag einen Deployment-Prozess mit den folgenden Eigenschaften finden:

  • Minimale Ausfallzeiten während des Bereitstellungsprozesses.
  • Minimal Zeit damit verbracht, die Daten hochgeladen werden.
  • Wenn der Bereitstellungsprozess App-Server spezifisch ist, dann muss der App-Server Open-Source sein.

Frage:

  • die genannten Anforderungen gegeben, was der Prozess optimale Einsatz ist?
War es hilfreich?

Lösung

Es wurde festgestellt, dass rsync funktioniert nicht gut, wenn Änderungen an einer WAR-Datei drücken. Der Grund dafür ist, dass WAR-Dateien sind im Wesentlichen ZIP-Dateien und sind standardmäßig mit Druckteildateien erstellt. Kleine Änderungen an den Teildateien (vor der Komprimierung) Ergebnis in großem Umfang Unterschiede in der ZIP-Datei, Rendering Delta-Transfer-Algorithmus rsync unwirksam.

Eine mögliche Lösung ist jar -0 ... zu verwenden, um die Original-WAR-Datei zu erstellen. Die -0 Option teilt den jar Befehl nicht die Mitglieder Dateien zu komprimieren, wenn die WAR-Datei zu erstellen. Dann, wenn rsync die alten und neuen Versionen der WAR-Datei vergleicht, sollte die Delta-Transfer Algorithmus in der Lage sein, kleine diffs zu erstellen. Dann vereinbaren, dass rsync die diffs sendet (oder Original-Dateien) in komprimierter Form; z.B. verwenden rsync -z ... oder einen komprimierten Datenstrom / Transport darunter.

EDIT: Je nachdem, wie die WAR-Datei strukturiert ist, kann es auch erforderlich sein, jar -0 ... zu verwenden, um Komponente JAR-Dateien zu erstellen. Diese JAR-Dateien gelten würde, die häufig Änderungen unterliegen (oder dass einfach umgebaut werden), anstatt zu stabilen 3. Dateien Partei JAR.

In der Theorie sollte dieses Verfahren eine deutliche Verbesserung geben über regelmäßige WAR-Dateien zu senden. In der Praxis habe ich nicht versucht, so kann ich nicht versprechen, dass es funktionieren wird.

Der Nachteil ist, dass die eingesetzte WAR-Datei deutlich größer sein wird. Dies kann zu längeren Webapp Startzeiten führen, obwohl ich den Verdacht, dass der Effekt marginal wäre.


Ein anderer Ansatz wäre ganz in Ihrer WAR-Datei, um zu sehen, ob Sie Bibliothek JAR-Dateien identifizieren, die sich nie ändern dürfte (fast) sind. Nehmen Sie diese JAR-Dateien aus der WAR-Datei, und stellen Sie sie separat in den common/lib Verzeichnis des Tomcat-Server; z.B. mit rsync.

Andere Tipps

Update:

Da diese Antwort zuerst geschrieben wurde, ein besserer Weg Krieg Dateien tomcat ohne Ausfallzeiten zu implementieren entstanden. In den letzten Versionen von tomcat können Sie Versionsnummern in Ihrem Krieg Dateinamen enthalten. So zum Beispiel, können Sie die Dateien ROOT##001.war und ROOT##002.war auf den gleichen Kontext gleichzeitig einzusetzen. Alles, was nach der ## wird von tomcat als Versionsnummer interpretiert und nicht Teil des Kontextpfades. Tomcat wird alle Versionen Ihrer App am Laufen halten und neue Anfragen und Sitzungen auf die neueste Version dienen, die ganz oben ist, während anmutig alte Anfragen und Sitzungen auf der Version abgeschlossen, mit denen sie gestartet. Angeben von Versionsnummern können auch über den tomcat-Manager und auch die catalina ant Aufgaben durchgeführt werden. Weitere Informationen hier .

Original Antwort:

Rsync neigt dazu, auf komprimierte Dateien unwirksam zu sein, da es Delta-Transfer-Algorithmus ist in Dateien für Änderungen sieht und eine kleine Änderung eine unkomprimierte Datei kann drastisch die resultierende komprimierte Version ändern. Aus diesem Grunde könnte es Sinn macht eine unkomprimierte Krieg Datei anstatt eine komprimierte Version in rsync, wenn die Netzwerk-Bandbreite zu einem Engpass erweist.

Was ist los mit der Verwendung der Tomcat-Manager-Anwendung Ihre Implementierungen zu tun? Wenn Sie den gesamten Krieg Datei laden möchten, direkt an den Tomcat Manager App von einem entfernten Standort nicht, können Sie es (unkomprimiert für oben genannten Gründen) rsync auf einen Platzhalter Standort auf dem Produktionsfeld Umpacken es zu einem Krieg, und gibt es dann an den Manager vor Ort. Es gibt eine nette Ameise Aufgabe, die Schiffe mit Tomcat Sie Skript ermöglicht den Tomcat Manager App-Bereitstellungen verwenden.

Es gibt einen zusätzlichen Fehler in Ihrem Ansatz, die Sie nicht erwähnt haben: Während der Anwendung teilweise (während eines rsync-Betriebes) eingesetzt wird, Ihre Anwendung in einem inkonsistenten Zustand sein könnte, wo geändert Schnittstellen nicht synchron sein können, neue / aktualisiert Abhängigkeiten nicht verfügbar sein kann, etc. auch, je nachdem, wie lange Ihre rsync Job nimmt, kann die Anwendung neu starten, tatsächlich mehrere Male. Sind Sie sich bewusst, dass Sie und das Hören-for-changed-files-und-Neustart Verhalten in Tomcat deaktivieren sollten? Es ist eigentlich nicht für Produktionssysteme empfohlen. Sie können einen manuellen oder Ameise scripted Neustart der Anwendung immer tun, um den Tomcat-Manager App.

Ihre Anwendung für die Nutzer bei einem Neustart, natürlich nicht zur Verfügung. Aber wenn Sie so besorgt über die Verfügbarkeit sind, haben Sie sicherlich redundantes Webserver hinter einem Load Balancer. Wenn eine aktualisierte WAR-Datei bereitstellen, können Sie vorübergehend die Load-Balancer haben alle Anfragen an andere Webserver senden, bis der Einsatz vorbei ist. Spülen und wiederholen Sie für Ihre anderen Web-Servern.

In jeder Umgebung, wo Ausfallzeiten ist eine Überlegung, die ausgeführt werden sicherlich eine Art Cluster von Servern Zuverlässigkeit durch Redundanz zu erhöhen. Ich würde einen Host aus dem Cluster übernehmen, aktualisieren Sie es, und es dann in die Cluster zurück zu werfen. Wenn Sie ein Update haben, die nicht in einer gemischten Umgebung (inkompatible Schemaänderung auf der db erforderlich, zum Beispiel) ausgeführt werden können, werden Sie haben, um die ganze Website herunterzunehmen, zumindest für einen Moment. Der Trick ist, zu bringen Ersatzprozesse bevor die Originale fallen.

tomcat als Beispiel - Sie CATALINA_BASE verwenden können, um ein Verzeichnis zu definieren, in denen alle Arbeitsverzeichnisse des Katers wird gefunden, aus dem ausführbaren Code getrennt werden. Jedes Mal, wenn ich Software bereitstellen, ich auf ein neues Basisverzeichnis bereitstellen, so dass ich neuen Code resident auf der Festplatte neben alten Code haben kann. Ich kann dann eine weitere Instanz von Tomcat starten, die auf das neue Basisverzeichnis verweist, erhalten alles begonnen und läuft, tauschen dann das alte Verfahren (Port-Nummer) mit der neuen in der Load-Balancer.

Wenn ich bin besorgt über die Sitzungsdaten über den Schalter zu bewahren, kann ich mein System so eingerichtet, dass jeder Host einen Partner hat, auf die sie von Sitzungsdaten repliziert. Ich kann einer dieser Hosts fallen, aktualisieren Sie es, bringen Sie es wieder nach oben, so dass sie die Sitzungsdaten wieder aufnimmt, und dann die beiden Hosts wechseln. Wenn ich mehrere Paare im Cluster haben, kann ich die Hälfte aller Paare fallen, dann eine Masse Schalter tun, oder ich kann in einer Zeit, sie ein Paar tun, abhängig von den Anforderungen der Freisetzung Anforderungen des Unternehmens, usw. . persönlich jedoch lieber, ich nur eher den sehr gelegentlichen Verlust einer aktiven Sitzung leiden Endnutzern ermöglichen, als du mit dem Versuch, mit Sitzungen intakt zu aktualisieren.

Es ist alles ein Kompromiss zwischen der IT-Infrastruktur, Release-Prozesskomplexität und Entwickler Aufwand. Wenn Ihr Cluster groß genug und Ihr Wunsch stark genug ist, ist es einfach genug, um ein System zu entwickeln, das ohne Ausfallzeiten ausgetauscht überhaupt für die meisten Updates werden kann. Große Schemaänderungen zwingen oft tatsächliche Ausfallzeiten, da aktualisierter Software in der Regel nicht das alte Schema aufnehmen kann, und man kann wohl mit dem Kopieren der Daten auf eine neue db-Instanz, tut das Schema Update nicht weg, und dann die Server auf die neue db Schalt, da haben Sie nach der neuen db daraus geklont wurde auf die alte geschrieben alle Daten verpasst. wenn Sie Ressourcen Natürlich haben, können Sie Entwickler Task die neue App mit modifizierenden für alle Tabellen neue Tabellennamen zu verwenden, die aktualisiert werden, und Sie können auf dem Live-db-Trigger in Kraft gesetzt, die korrekt die neuen Tabellen mit Daten werden aktualisiert, es wird von der früheren Version zu den alten Tabellen geschrieben (oder vielleicht Ansichten verwenden ein Schema von den andere zu emulieren). Bringen Sie Ihren neuen App-Server und tauschen sie in den Cluster. Es gibt eine Tonne von Spielen Sie um spielen können Ausfallzeiten zu minimieren, wenn Sie die Entwicklungsressourcen haben, sie zu bauen.

Die vielleicht nützlichste Mechanismus für Ausfallzeiten während der Software-Upgrades zu reduzieren ist, um sicherzustellen, dass Ihre Anwendung in einem Read-Only-Modus arbeiten kann. Das wird einige notwendige Funktionalität, um Ihre Benutzer liefern, sondern lassen Sie die Möglichkeit, systemweite Änderungen, die Datenbankänderungen und solche erfordern. Legen Sie Ihre App in Nur-Lese-Modus, dann klonen die Daten, Update-Schema, bringen neue App-Server gegen neue db, dann schalten Sie den Load-Balancer die neue App-Server zu verwenden. Ihre einzige Ausfallzeit ist die Zeit, die zum Umschalten in Nur-Lese-Modus und die Zeit benötigt, um die Konfiguration des Load Balancer zu ändern (von denen die meisten es ohne Ausfallzeit verarbeiten kann auch immer).

Mein Rat ist, rsync mit Explosions Versionen zu verwenden, sondern eine WAR-Datei bereitstellen.

  1. Erstellen Sie temporäre Ordner in der Live-Umgebung, in der Sie die Version von Webapp explodiert werden.
  2. Rsync explodierte Versionen.
  3. Nach erfolgreicher rsync eine WAR-Datei in temporären Ordner in der Live-Umgebung Maschine erstellen.
  4. Ersetzen Sie alten Krieg im Server-Verzeichnis deploy mit neuen aus temporären Ordnern.

Austausch alter Krieg mit neuem wird in JBoss Containern empfohlen beacause it'a Atom- und schnelle Bedienung (die auf Tomcat basiert) und es ist sicher, dass, wenn deployer wird gesamte Anwendung startet in entfalteten Zustand sein wird.

Können Sie nicht eine lokale Kopie der aktuellen Web-Anwendung auf dem Web-Server machen, rsync zu diesem Verzeichnis und dann vielleicht sogar symbolische Links verwenden, in einem „go“, Punkt Tomcat zu einem neuen Einsatz ohne viele Ausfallzeiten?

Ihr Ansatz den extrahierten Krieg in rsync ist ziemlich gut, auch der Neustart, da ich glaube, dass ein Produktionsserver nicht Hot-Deployment aktiviert haben soll. So ist der einzige Nachteil, die Ausfallzeiten, wenn Sie müssen den Server neu zu starten, oder?

Ich gehe davon aus all Zustand Ihrer Anwendung in der Datenbank halten, so haben Sie kein Problem mit einigen Benutzern auf einer App-Server-Instanz arbeiten, während andere Benutzer auf einer anderen App-Server-Instanz sind. Wenn ja,

Ausführen zwei Applikationsserver : den zweiten App-Server Starten Sie (die auf anderem TCP-Ports lauscht) und Bereitstellen Ihre Anwendung gibt. Nach der Bereitstellung Aktualisieren der Konfiguration des Apache httpd (mod_jk oder Mod_proxy) zu dem zweiten Anwendungsserver zu verweisen. den Apache Prozess Anmutig neu zu starten. Auf diese Weise haben Sie keine Ausfallzeiten und neue Benutzer und Anfragen müssen an den neuen App-Server automatisch weitergeleitet.

Wenn Sie von dem App-Server des Clustering und Sitzungsreplikationsunterstützung machen können, wird es auch glatt für Benutzer sein, die in der aktuell angemeldet sind, als der zweite App-Server synchronisieren sobald es beginnt. Dann, wenn es keine an den ersten Server zugreift, schalten Sie ihn aus.

Dies ist abhängig von Ihrer Anwendungsarchitektur.

Einer meiner Anwendungen sitzt hinter einem Load-Balancing-Proxy, von dem ich einen gestaffelten Einsatz durchführen -. Effektiv Ausfallzeiten zu beseitigen

Wenn statische Dateien ein großer Teil Ihres großen Krieges (100Mo ist ziemlich groß), dann sie außerhalb des IST setzen und sie auf einem Web-Server bereitstellen (zum Beispiel Apache) vor dem Anwendungsserver kann bis den Dinge beschleunigen. Hinzu kommt, dass, tut Apache in der Regel einen besseren Job bei statischen Dateien als eine Servlet-Engine dient tut (auch wenn die meisten von ihnen erhebliche Fortschritte in diesem Bereich gemacht).

Also, anstatt eine dicke, fette WAR produzieren, legte es auf Diät und produzieren:

  • a big fat ZIP mit statischen Dateien für Apache
  • ein weniger Fett IST für die Servlet-Engine.

Optional geht weiter in dem Prozess des IST dünner zu machen: wenn möglich, implementieren Grails und andere JAR-Dateien, die nicht häufig ändern (was wahrscheinlich der Fall des meisten von ihnen ist) auf der Anwendungsserverebene

Wenn Sie bei der Herstellung eines leichteres IST gelingen, würde ich nicht von Mühe rsyncing Verzeichnisse statt Archiven.

Stärken dieses Ansatzes:

  1. Die statischen Dateien können hot „im Einsatz“ auf Apache (z einen symbolischen Link verwenden, um auf das aktuelle Verzeichnis zeigt, entpacken Sie die neuen Dateien, aktualisieren Sie die Symlink und voilà).
  2. Der Krieg wird dünner sein und es wird weniger Zeit in Anspruch nehmen, um es einzusetzen.

Schwäche dieses Ansatzes:

  1. Es gibt einen weiteren Server (Web-Server), so diese add (etwas) mehr Komplexität.
  2. Sie müssen den Build-Skripte ändern (keine große Sache IMO).
  3. Sie müssen die rsync Logik ändern.

Ich bin mir nicht sicher, ob dies Ihre Frage beantwortet, aber ich werde einfach auf den Deployment-Prozess teilen, die ich in den wenigen Projekten verwenden oder Begegnung ich.

Similiar Sie, ich habe nicht immer eine volle Krieg Umschichtung oder Update erinnern zu machen. Die meiste Zeit sind meine Updates auf wenige jsp Dateien beschränkt, vielleicht eine Bibliothek, einige Klassendateien. Ich bin in der Lage zu verwalten und zu bestimmen, welche die betroffenen Artefakte sind, und in der Regel, wir diese Aktualisierung in einer ZIP-Datei, zusammen mit einem Update-Skript verpackt. Ich werde den Update-Skript ausführen. Das Skript funktioniert wie folgt vor:

  • Backup der Dateien, die überschrieben werden, vielleicht in einen Ordner mit dem heutigen Datum und Uhrzeit.
  • Packen Sie meine Dateien
  • Stoppen Sie den Anwendungsserver
  • Verschieben Sie die Dateien über
  • Starten Sie den Anwendungsserver

Wenn Ausfallzeiten ein Anliegen, und sie sind in der Regel, meine Projekte in der Regel HA sind, auch wenn sie nicht Staat teilen, aber mit einem Router, die klebrig-Session Routing bieten.

Eine andere Sache, die ich neugierig bin wäre, warum die Notwendigkeit zu rsync? Sie sollten in der Lage zu wissen, was die erforderlichen Änderungen sind, indem sie auf dem Staging / Entwicklungsumgebung zu bestimmen, nicht Delta prüft mit Live-Auftritten. In den meisten Fällen würden Sie stimmen haben Ihre rsync Dateien sowieso zu ignorieren, wie bestimmte Eigenschaft Dateien, die Ressourcen einen Produktionsserver verwenden, wie Datenbankverbindung definieren, SMTP-Server, etc.

Ich hoffe, dass dies hilfreich ist.

An was ist Ihr PermSpace eingestellt? Ich würde erwarten, dass dies auch zu sehen, wächst aber sollte nach unten geht nach der Sammlung der alten Klassen? (Oder hat die Classloader noch herumsitzen?)

Denken outloud, könnten Sie zu einem separaten Versions- oder Datums genannten Verzeichnis rsync. Wenn der Container symbolische Links unterstützt, könnte SIGSTOP Sie das Root-Prozess, schalten Sie das Dateisystem root Kontext über symbolische Verknüpfung und dann SIGCONT?

Wie bei der frühen Kontext neu gestartet. Alle Behälter haben Konfigurationsoptionen Auto-redeploy auf Klassendatei oder statische Ressource Änderungen zu deaktivieren. Sie können sich wahrscheinlich nicht deaktivieren Auto auf web.xml Änderungen redeploys so dass diese Datei die letzte ist zu aktualisieren. Also, wenn Sie die automatische redeploy deaktivieren und aktualisieren Sie die web.xml als das letzte Sie den Kontext Neustart sehen werden nach das ganze Update.

Wir haben die neue Version der Webapp in ein separates Verzeichnis laden, dann entweder verschieben Sie es mit der Lauf ein tauschen, oder Symlinks verwenden. Zum Beispiel haben wir einen Symlink im Kater webapps Verzeichnis mit dem Namen „myapp“, die auf den aktuellen Webapp Punkte genannt „myapp-1.23“. Wir laden Sie die neue Webapp „myapp-1.24“. Wenn alles bereit ist, den Server stoppen, den Symlink entfernen und eine neue auf die neue Version zeigt machen, dann wieder den Server starten.

Wir deaktivieren Auto-Reload auf Produktionsservern für Leistung, aber auch so, in der Webapp-Dateien mit in einer nicht-atomaren Weise zu ändern können Probleme verursachen, als statische Dateien oder auch JSP-Seiten konnten in einer Weise ändern, die defekten Links führen oder schlimmer.

In der Praxis werden die Webapps tatsächlich auf einem gemeinsam genutzten Speichergerät befindet, so geclustert, Lastenausgleich und Failover-Server haben alle den gleichen Code zur Verfügung.

Der Hauptnachteil für Ihre Situation ist, dass der Upload wird länger dauern, da Ihre Methode rsync nur Übertragung geändert oder hinzugefügt Dateien ermöglicht. Sie könnten die alten Webapp-Ordner auf den neuen kopieren ersten und den rsync, wenn es einen erheblichen Unterschied macht, und wenn es wirklich ein Problem.

Tomcat 7 hat eine nette Funktion namens „ parallel Einsatz “, der für diesen Anwendungsfall ausgelegt.

Der Kern ist, dass Sie die .war in ein Verzeichnis zu erweitern, entweder direkt unter webapps / oder symbolischen Links. Aufeinander folgende Versionen der Anwendung sind in Verzeichnissen app##version genannt, zum Beispiel myapp##001 und myapp##002. Tomcat bestehende Sitzungen behandelt auf die alte Version gehen und neue Sitzungen auf die neue Version gehen.

Der Haken ist, dass Sie sein müssen sehr vorsichtig mit PermGen Lecks. Dies gilt insbesondere mit Grails, die eine Menge PermGen verwendet. VisualVM ist dein Freund.

Verwenden Sie einfach 2 oder mehr tomcat-Server mit einem Proxy darüber. Das Proxy kann von Apache / nignix / haproxy sein.

Jetzt in jedem des Proxy-Server ist es "in" und "out" url mit Ports konfiguriert werden.

Sie zuerst Ihren Krieg im tomcat kopieren, ohne den Dienst stoping. Sobald Krieg entfaltet wird es automatisch vom tomcat Motor geöffnet wird.

Hinweis cross check unpackWARs = "true" und AutoDeploy = "true" im Knoten "Host" innerhalb server.xml

Es sieht mag dieses

  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">

Jetzt die Protokolle von Kater sehen. Wenn kein Fehler ist es bedeutet, dass es erfolgreich ist oben.

treffen nun alle APIs für die Prüfung

Jetzt kommen Sie zu Ihrem Proxy-Server.

Sie einfach die Abbildung Hintergrund URL ändern mit dem Namen des neuen Krieges. Da die Registrierung bei dem Proxy-Server wie Apache / nignix / HAProxy nahm sehr weniger Zeit, werden Sie minimale Ausfallzeiten fühlen

Siehe - https://developers.google.com/speed/pagespeed/module / domains für die Zuordnung von URLs

Sie sind mit dem Harz, Harz hat Unterstützung für Web-App Versionierung gebaut.

http://www.caucho.com/resin-4.0/ admin / deploy.xtp # VersioningandGracefulUpgrades

Update:. Es ist Watchdog-Prozess auch mit permgenspace Problemen helfen kann

Nicht ein "best practice", sondern etwas, das ich nur dachte.

Wie wäre es die Webapp durch eine DVCS wie git bereitstellen?

Auf diese Weise können git ausrechnen lassen, welche an den Server zu übertragen Dateien. Sie haben auch eine schöne Möglichkeit, es wieder heraus, wenn sich herausstellt, gesprengt werden, einfach eine revert!

Ich schrieb einen Bash-Skript, das einige Parameter und rsyncs die Datei zwischen den Servern erfolgt. Beschleunigt rsync übertragen viel für größere Archive:

https://gist.github.com/3985742

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top