Domanda

Attualmente sto lavorando su un progetto j2ee che è in beta ormai da un po'.Al momento stiamo solo risolvendo alcuni dei problemi con il processo di distribuzione.Nello specifico, ci sono una serie di file incorporati nel war (alcuni file xml e .properties) che necessitano di versioni diverse da distribuire a seconda che ci si trovi in ​​un ambiente di sviluppo, test o produzione.Cose come livelli di log, pool di connessioni, ecc.

Quindi mi chiedevo come gli sviluppatori qui strutturano il loro processo di distribuzione delle webapp.Scarichi quanta più configurazione possibile sul server delle applicazioni?I file delle impostazioni vengono sostituiti a livello di codice prima della distribuzione?Scegli una versione durante il processo di creazione?Modificare manualmente le guerre?

Inoltre, fino a che punto ti spingi a fornire dipendenze attraverso le librerie statiche dei server delle applicazioni e quanto metti in guerra gli stessi?Tutto questo solo per avere un’idea di quale sia la pratica comune (o forse migliore) al momento.

È stato utile?

Soluzione

Lavoro in un ambiente in cui un team di server separato esegue la configurazione dei server QA e di produzione per le nostre applicazioni.Ogni applicazione viene generalmente distribuita su due server in QA e tre server in produzione.Il mio team di sviluppo ha scoperto che è meglio ridurre al minimo la quantità di configurazione richiesta sul server inserendo quanta più configurazione possibile in guerra (o orecchio).Ciò semplifica la configurazione del server e riduce al minimo la possibilità che il team del server configuri il server in modo errato.

Non abbiamo una configurazione specifica per la macchina, ma abbiamo una configurazione specifica per l'ambiente (sviluppo, QA e produzione).Abbiamo file di configurazione memorizzati nel file war che sono nominati in base all'ambiente (es.dev.properties, qa.properties, prod.properties).Inseriamo una proprietà -D sulla riga di comando Java della VM del server per specificare l'ambiente (es.java -Dapp.env=prod ...).L'applicazione può cercare la proprietà di sistema app.env e utilizzarla per determinare il nome del file delle proprietà da utilizzare.

Suppongo che se hai un numero limitato di proprietà specifiche della macchina, potresti specificarle anche come proprietà -D.Commons Configuration fornisce un modo semplice per combinare i file delle proprietà con le proprietà di sistema.

Configuriamo i pool di connessioni sul server.Diamo al pool di connessioni lo stesso nome per ogni ambiente e indirizziamo semplicemente i server assegnati a ciascun ambiente al database appropriato.L'applicazione deve conoscere solo il nome del pool di connessioni.

Altri suggerimenti

Penso che se le proprietà sono specifiche della macchina/distribuzione, allora appartengono alla macchina.Se ho intenzione di concludere le cose in una guerra, dovrebbe essere drop-innable, il che significa nulla che sia specifico per la macchina su cui è in esecuzione.Questa idea verrà meno se la guerra avrà proprietà dipendenti dalle macchine.

Quello che mi piace fare è creare un progetto con un file Properties.example, ogni macchina ha un file .properties che risiede da qualche parte a cui la guerra può accedervi.

Un modo alternativo sarebbe quello di avere compiti di formiche, ad es.per dev-war, stage-war, prod-war e avere i set di proprietà parte del progetto, integrati nella build di guerra.Non mi piace tanto perché finirai per avere cose come le posizioni dei file su un singolo server come parte della creazione del tuo progetto.

rispetto ai file di configurazione, credo Quello di Steve la risposta è la migliore finora.Aggiungerei il suggerimento di creare file esterni relativi al percorso di installazione del file war: in questo modo puoi avere più installazioni di war nell'unico server con diverse configurazioni.

per esempio.Se il mio dev.war viene disimballato /opt/tomcat/webapps/dev, allora userei ServletContext.getRealPath per trovare la cartella di base e il nome della cartella war, in modo che i file di configurazione vivano ../../config/dev relativo alla guerra, o /opt/tomcat/config/dev per assoluto.

Sono anche d'accordo con Conto di mettere il meno possibile in questi file di configurazione esterni.Utilizzando il database o JMX a seconda dell'ambiente per archiviare quanto ha senso.La configurazione di Apache Commons ha un file bell'oggetto per gestire le configurazioni supportate da una tabella di database.

Per quanto riguarda le biblioteche, sono d'accordo sconosciuto per avere tutte le librerie in WEB-INF/lib cartella nel file war (autoconfezionato).Il vantaggio è che ogni installazione dell'applicazione è autonoma e potresti avere diverse build di war utilizzando diverse versioni delle librerie contemporaneamente.

Lo svantaggio è che utilizzerà più memoria poiché ogni applicazione web avrà la propria copia delle classi, caricata dal proprio caricatore di classi.

Se ciò rappresenta una vera preoccupazione, potresti inserire i jar nella cartella della libreria comune per il tuo contenitore servlet ($CATALINA_HOME/lib per il gatto).Tutte le installazioni della tua applicazione web in esecuzione sullo stesso server devono però utilizzare le stesse versioni delle librerie.(In realtà, questo non è del tutto vero in quanto potresti inserire versioni prioritarie nell'individuo WEB-INF/lib cartella se necessario, ma sta diventando piuttosto complicato da mantenere.)

In questo caso creerei un programma di installazione automatizzato per le librerie comuni, utilizzando InstallShield o NSIS o equivalente per il tuo sistema operativo.Qualcosa che possa rendere facile capire se disponi del set di librerie più aggiornato e eseguire aggiornamenti, downgrade, ecc.

Di solito creo due file di proprietà:

  • uno per le specifiche dell'app (messaggi, parole "magiche" interne) incorporati nell'app,
  • l'altro per le specifiche dell'ambiente (accesso al database, livelli di registro e percorsi...) esposto sul percorso di classe di ciascun server e "bloccato" (non fornito con la mia app).Di solito li "mavenise" o "antise" per inserire valori specifici, a seconda dell'ambiente di destinazione.
  • I ragazzi fantastici usano JMX per mantenere la configurazione della loro app (conf può essere modificata in tempo reale, senza ridistribuirla), ma è troppo complessa per le mie esigenze.

Librerie del server (statiche?):Sconsiglio vivamente l'uso della libreria server nelle mie app poiché aggiunge dipendenza al server:

  1. IMO, la mia app deve essere "autoconfezionata":abbandonando la mia guerra, e questo è tutto.Ho visto guerre con 20 Mb di jar dentro e questo non mi disturba.
  2. Una best practice comune è limitare le dipendenze esterne a ciò che viene offerto dal dogma J2EE:le API J2EE (uso di Servlet, Ejbs, Jndi, JMX, JMS...).La tua app deve essere "server indipendente".
  3. L'inserimento delle dipendenze nella tua app (war, ear, wathever) si autodocumenta:sai da quali librerie dipende la tua app.Con le librerie del server, devi documentare chiaramente queste dipendenze poiché sono meno ovvie (e presto i tuoi sviluppatori dimenticheranno questa piccola magia).
  4. Se aggiorni il tuo appserver, cambieranno anche le possibilità che la libreria del server da cui dipendi.Gli editor di AppServer non dovrebbero mantenere la compatibilità sulle loro librerie interne da una versione all'altra (e la maggior parte delle volte non lo fanno).
  5. Se usi una libreria ampiamente utilizzata incorporata nel tuo appServer (mi viene in mente la registrazione di Jakarta Commons, alias jcl) e desideri aggiornare la sua versione per ottenere le funzionalità più recenti, corri l'enorme rischio che il tuo appServer non la supporti.
  6. Se ti affidi a un oggetto server statico (in un campo statico di una classe server, ad es.una mappa o un registro), dovrai riavviare il tuo appserver per pulire questo oggetto.Perdi la possibilità di ridistribuire a caldo la tua app (il vecchio oggetto server esisterà ancora tra le ridistribuzioni).L'utilizzo di oggetti a livello di appServer (diversi da quelli definiti da J2EE) può portare a bug sottili, soprattutto se questo oggetto è condiviso tra più app.Ecco perché sconsiglio vivamente l'uso di oggetti che risiedono in un campo statico di una libreria appServer.

Se hai assolutamente bisogno di "questo oggetto nel jar di questo appserver", prova a copiare il jar nella tua app, sperando che non ci sia dipendenza dal jar di un altro server e controllando la politica di caricamento delle classi della tua app (prendo l'abitudine di inserire un classloading "parent last" politica su tutte le mie app:Sono sicuro che non sarò "inquinato" dai jar del server, ma non so se sia una "migliore pratica").

Ho inserito tutta la configurazione nel database.Il contenitore (Tomcat, WebSphere, ecc.) mi dà accesso alla connessione iniziale al database e da quel momento in poi tutto esce dal database.Ciò consente più ambienti, clustering e modifiche dinamiche senza tempi di inattività (o almeno senza ridistribuzione).Particolarmente interessante è la possibilità di modificare al volo il livello del registro (anche se avrai bisogno di una schermata di amministrazione o di un aggiornamento in background per rilevare le modifiche).Ovviamente questo funziona solo per cose che non sono necessarie per avviare l'app, ma in generale è possibile accedere al database abbastanza rapidamente dopo l'avvio.

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