Domanda

Abbiamo un'applicazione server Java che funziona su un numero di computer, tutti collegati a Internet, alcuni dietro i firewall. Dobbiamo aggiornare in remoto i file JAR e gli script di avvio da un sito centrale, senza alcuna notevole interruzione dell'app stessa.

Il processo deve essere incustodito e infallibile (ovvero non possiamo permetterci di interrompere l'app a causa di interruzioni anticipate di Internet).

In passato abbiamo utilizzato una varietà di script e utilità esterni per gestire attività simili, ma poiché hanno le loro dipendenze, il risultato è più difficile da mantenere e meno portatile. Prima di fare qualcosa di nuovo, voglio ottenere alcuni input dalla community.

Qualcuno ha già trovato una buona soluzione per questo? Hai idee o suggerimenti?

Solo per chiarire: questa app è un server, ma non per applicazioni web (non ci sono contenitori webapp o file WAR qui). È solo un programma Java autonomo.

È stato utile?

Soluzione

Non hai specificato il tipo di app server - suppongo che non stai eseguendo app Web (poiché la distribuzione di una WAR fa già quello di cui stai parlando e molto raramente hai bisogno di un'app Web per esegui gli aggiornamenti del tipo pull. Se stai parlando di un'app Web, è comunque possibile applicare la seguente discussione: implementerai solo il controllo degli aggiornamenti e il ping-pong per il file WAR anziché i singoli file).

Potresti dare un'occhiata a jnlp - WebStart si basa su questo (questa è una tecnologia di distribuzione delle applicazioni client), ma sono abbastanza sicuro che potrebbe essere personalizzato per eseguire aggiornamenti per un'app di tipo server. Indipendentemente da ciò, jnlp fa un ottimo lavoro nel fornire descrittori che possono essere usati per scaricare le versioni richieste dei JAR richiesti ...

Alcune considerazioni generali su questo (abbiamo diverse app nello stesso bucket e stiamo prendendo in considerazione un meccanismo di aggiornamento automatico):

  1. Prendi in considerazione l'idea di avere un file bootstrap.jar in grado di leggere un file jnlp e scaricare i barattoli necessari / aggiornati prima di avviare l'applicazione.

  2. I file JAR possono essere aggiornati anche mentre è in esecuzione un'app (almeno su Windows, che è probabilmente il sistema operativo che blocca i file in esecuzione). È possibile riscontrare problemi se si utilizzano caricatori di classi personalizzati o si dispone di un gruppo di JAR che potrebbero essere caricati o scaricati in qualsiasi momento, ma se si creano meccanismi per impedirlo, quindi sovrascrivere i JAR e riavviare l'app dovrebbe essere sufficiente per l'aggiornamento.

  3. Anche se è possibile sovrascrivere i JAR, potresti prendere in considerazione un approccio ping-pong per il tuo percorso lib (se non hai già il tuo launcher configurato per leggere automaticamente tutti i file jar nella cartella lib e aggiungile automaticamente al percorso della classe, quindi è qualcosa che vuoi davvero fare). Ecco come funziona il ping-pong:

L'app si avvia e guarda lib-ping \ version.properties e lib-pong \ version.properties e determina quale è più recente. Diciamo che lib-ping ha una versione successiva. Il programma di avvio cerca lib-ping * .jar e aggiunge tali file al CP durante l'avvio. Quando esegui un aggiornamento, scarichi i file jar in lib-pong (o copia i file jar da lib-ping se vuoi risparmiare larghezza di banda e il JAR non è cambiato in realtà, ma raramente ne vale la pena!). Dopo aver copiato tutti i JAR in lib-pong, l'ultima cosa che fai è creare il file version.properties (in questo modo un aggiornamento interrotto che si traduce in una cartella lib parziale può essere rilevato ed eliminato). Infine, riavvii l'app e bootstrap rileva che lib-pong è il percorso di classe desiderato.

    Il ping-pong
  1. come descritto sopra consente un rollback. Se lo si progetta correttamente, è possibile avere un pezzo della tua app da cui testare il diavolo e quindi non modificare mai i controlli per vedere se dovrebbe eseguire il rollback di una determinata versione. In questo modo se sbagli e distribuisci qualcosa che rompe l'app, puoi invalidare la versione. Questa parte dell'applicazione deve solo eliminare il file version.properties dalla cartella lib- * non valida, quindi riavviare. È importante mantenere questa parte sporca semplice perché è il tuo fail safe.

  2. Puoi avere più di 2 cartelle (invece di ping / pong, basta avere lib-yyyymmdd ed eliminare tutte, tranne le 5 più recenti, per esempio). Ciò consente un rollback più avanzato (ma più complicato!) Dei JAR.

Altri suggerimenti

Dovresti assolutamente dare un'occhiata a OSGi, è stato creato proprio per questi casi (specialmente per prodotti embedded) ed è utilizzato da un gran numero di aziende. Puoi aggiornare jar " bundles " ;, aggiungili e rimuovili mentre l'app è in esecuzione. Non l'ho usato da solo, quindi non conosco la qualità dei framework / server open source, ma ecco un mucchio di link utili per iniziare:

http://www.osgi.org/Main/HomePage
http://www.aqute.biz/Code/Bnd
http://blog.springsource.com/2008/02/18 / OSGi-bundle creazione-/
http://blog.springsource.com/
http://www.knopflerfish.org/
http://felix.apache.org/site/index.html

Consiglierei Capistrano per la distribuzione multi-server. Mentre è progettato per la distribuzione di app Rails, l'ho visto usato con successo per distribuire applicazioni Java.

Link: Capistrano 2.0 non solo per Rails

I vasetti non possono essere modificati mentre la JVM è in esecuzione su di esso e comporteranno errori. Ho provato attività simili e il meglio che mi è venuto in mente è fare una copia del Jar aggiornato e passare allo script di avvio per guardare quel Jar. Una volta che hai il Jar aggiornato, avvialo e attendi che il vecchio Jar finisca dopo avergli dato il segnale per farlo. Sfortunatamente questo significa una perdita di GUI ecc. Per un secondo, ma serializzare la maggior parte delle strutture in Java è facile e la GUI corrente potrebbe essere trasferita all'applicazione aggiornata prima della chiusura effettiva (alcune cose potrebbero non essere serializzabili però!).

È molto difficile rendere atomico l'aggiornamento, soprattutto se è necessario eseguire un aggiornamento del database.

Ma, in caso contrario, ciò che puoi fare è prima assicurarti che l'applicazione possa essere eseguita da un percorso relativo. Cioè, puoi mettere la tua app in una directory e tutti i file importanti vengono trovati relativi a quella posizione, in modo che la posizione effettiva di installazione non sia davvero importante.

Successivamente, duplica la tua installazione. Ora hai " in esecuzione " versione e hai la "nuova" quot versione.

Aggiorna il " nuovo " versione usando qualunque tecnologia ti piaccia (FTP, rsync, nastro di carta, qualunque cosa galleggi la tua barca).

Verifica la tua installazione (checksum, test di unità rapidi, qualunque cosa ti serva - se vuoi, avvialo anche su una porta di prova.

Quando sei soddisfatto della nuova installazione, lungo l'istanza in esecuzione originale, RENAME la directory originale (mv application application_old), rinomina la directory NEW (mv application_new application) e riavviala.

Il tempo di inattività viene ridotto allo spegnimento del server e al tempo di avvio (poiché la ridenominazione è "gratuita").

Se, per caso, rilevi un errore critico, la tua versione originale è ancora lì. Arrestare il nuovo server, rinominarlo, riavviare il vecchio. Fallback molto veloce.

L'altra cosa bella è che la tua infrastruttura di servizio è statica (come i tuoi script rc, cron job, ecc.) poiché puntano all'applicazione " directory e non cambia.

Può anche essere fatto con collegamenti software invece di rinominare le directory. in entrambi i casi va bene.

Ma la tecnica è semplice e quasi a prova di proiettile se la tua applicazione collabora.

Ora, se hai modifiche al DB, beh, questo è un problema completamente diverso. Idealmente, se è possibile apportare modifiche al proprio DB "retrocompatibile", si spera che la vecchia versione dell'applicazione possa essere eseguita sul nuovo schema, ma ciò non è sempre possibile.

Credo che puoi distribuire a caldo i file JAR se usi un server di app basato su OSGi come SpringSource dm Server . Non l'ho mai usato da solo, ma conoscendo la qualità generale del portafoglio Spring, sono sicuro che vale la pena dare un'occhiata.

Usiamo Eclipse quale sistema di aggiornamento di OSGi e la nostra esperienza è ottima.

consigliato!

L'ultima versione di Java Web Start consente di iniettare un'applicazione nella cache locale senza richiamare effettivamente il programma e può essere contrassegnata come "offline". Poiché la cache è ciò che viene utilizzato per richiamare il programma, verrà aggiornato solo per la prossima esecuzione. Perché questo funzioni molto probabilmente avrai bisogno di vasetti con i numeri di versione nel loro nome (ad es. Our-library-2009-06-01.jar).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top