Modelli di configurazione di applicazioni Web Java

Esistono modelli o best practice che possono essere utilizzati per semplificare la modifica dei profili di configurazione per le applicazioni web java in più ambienti. es. URL JDBC, end-point SOAP, ecc.

Come sfondo per chiarire la mia domanda, lavoro con molte grandi applicazioni web java che durante un determinato ciclo di rilascio si muovono attraverso 6 diversi ambienti; sviluppo, integrazione, controllo qualità, prestazioni e infine distribuzione su più server di produzione. In ogni ambiente, la configurazione deve cambiare. Al momento, la maggior parte delle modifiche alla configurazione per ogni distribuzione viene eseguita manualmente, il che richiede sia tempo che essere aperto agli errori.
C’è un modo per ritirare l’intervento manuale da questo processo?

Di solito tendo a lavorare di più con .NET, quindi il mio Java è abbastanza arrugginito. Sono abbastanza sicuro che ciò funzionerebbe in qualsiasi lingua con un piccolo ritouch.

Utilizziamo un’estensione del sistema di configurazione .NET che ci consente di utilizzare impostazioni specifiche per l’ambiente e / o l’applicazione in combinazione con una configurazione più globale. Il sistema di configurazione utilizza un’impostazione globale per ogni macchina identifica come dev, beta o produzione (impostazione predefinita). Un set di file caricati in ordine e l’impostazione dell’ultimo file sostituisce qualsiasi impostazione definita in un file precedentemente caricato. I file vengono caricati nel seguente ordine:

  1. Impostazioni globali
  2. Impostazioni specifiche dell’applicazione
  3. Override dell’ambiente specifico dell’applicazione

Tutti i file sono nel controllo del codice sorgente e poiché l’ambiente è definito sulla macchina su cui è in esecuzione l’applicazione; poiché non accederà alla configurazione “beta” a meno che la configurazione della macchina non lo identifichi come “beta”, possiamo promuovere tutti i file di configurazione senza il timore di indirizzare inavvertitamente la nostra applicazione di produzione su un database di sviluppo.

Sono sorpreso che nessuno abbia citato l’API Jakarta Commons Configuration ( http://commons.apache.org/configuration/ ) per rispondere a questa domanda. Ti consente di avere una gerarchia di file (o altre fonti di configurazione come XML, JNDI, JDBC, ecc.). Questo è ciò di cui parlava Jeremy Seghi e ti dà un buon modo per avere sia i valori predefiniti che gli override locali.

La parte migliore è che si tratta di una soluzione di lavoro collaudata in modo da non dover creare qualcosa da soli.

Ecco alcune pratiche possibili che ho usato o incontrato. La combinazione di questi è solitamente necessaria nella pratica.

Sostituendo i valori delle variabili in conffiles durante la costruzione

Ecco un esempio di come questo può essere fatto con Apache Ant. Le proprietà ant ( ${var.name} ) possono essere controllate con i file di configurazione build:

              

La cosa buona è che si ottiene un controllo preciso sulle diverse configurazioni in fase di costruzione. Ciò che è negativo è che il sistema tende a diventare molto complesso e difficile da mantenere se si utilizza questo metodo in modo estensivo per un gran numero di diverse configurazioni. Inoltre, dover build i conffiles significa anche rallentare i cicli di sviluppo.

Sostituendo le variabili da conf inside war all’avvio webapp

Questo è quello che faccio solitamente quando uso Spring Framework, anche se c’è solo una configurazione ansible, ottenendo i benefici della separazione delle preoccupazioni. Con Spring, è ansible sostituire i valori di conf con PlaceholderPropertyConfigurer all’interno del contesto Spring all’avvio di webapp. In questo caso, devi comunque scegliere la configurazione corretta, che può essere configurata per esempio in fase di costruzione.

Rispetto al tempo di costruzione che sostituisce, è più facile manipolare temporaneamente i valori in una webapp non compressa, se necessario. Ovviamente, è necessario riavviare la webapp se si modifica qualcosa e le modifiche manuali non verranno mantenute tra le ridistribuzioni di webapp. Spring è anche limitato al contesto Spring, quindi questo non funziona ad esempio in web.xml (ma avere variabili in web.xml dovrebbe essere evitato comunque a causa dei suoi limiti).

Lettura della conf locale da un file predefinito

Questo approccio è probabilmente il più facile da configurare: basta inventare un percorso per il file di configurazione, ad esempio $HOME/mywebapp/conf.properties e rendere la tua webapp in qualche modo leggibile all’avvio.

La cosa buona qui è che non ti devi preoccupare della conf quando costruisci / distribuisci la webapp. Ad ogni modo, dovresti avere alcuni preregolati conf, che possono essere sovrascritti dal locale conf.

Avere il conf in un database

Questa è la soluzione più flessibile per l’override dei parametri di conf, ma può anche essere complicata in alcuni casi. Avere il conf in una tabella con colonne name e value dovrebbe funzionare per la maggior parte dei casi.

Ovviamente, non è ansible configurare gli URL di connessione JDBC in una tabella di database, ma questa è una buona soluzione per un semplice conf di testo / numerico che influisce sull’operazione webapp dopo che è stata impostata la connessione db. Per evitare una penalizzazione delle prestazioni, assicurati di aver memorizzato nella cache in qualche modo il conf se verrà acceduto frequentemente.

Pratiche extra

Come sottolineato da kgiannakakis, aiuta anche a configurare una pagina di diagnostica di configurazione di qualche tipo per la tua app.

Ciò dipenderà in gran parte dalle opzioni che i server di applicazioni Web offrono. Disponiamo di più ambienti per JBoss con diversi URL JDBC, il nome JNDI rimane lo stesso su tutti i server, solo la configurazione dell’istanza locale cambia, quindi non c’è nulla di sbagliato da build a build.

Immagino che la risposta breve sia che la migliore pratica è esternalizzare le configurazioni e mantenere un buon file sul posto con le impostazioni corrette per ogni server, e fare in modo che l’app Web legga tale configurazione. La natura esatta dell’esternalizzazione e della lettura dipenderà dalla configurazione specifica e dal server delle applicazioni.

EDIT: Queste configurazioni non esistono come parte della guerra (orecchio nel nostro caso) in questo modo non vengono sovrascritte.

All’inizio hanno tutte le impostazioni di configurazione che cambiano di frequente in un unico posto. È davvero difficile, se è necessario configurare JNDI, modificare i valori del database e modificare i file di proprietà, tutti allo stesso tempo, al fine di completare la configurazione. Preferisci il mezzo che è più facile da modificare e anche più semplice verificare che tutto sia impostato correttamente. Direi che i file di proprietà sono la soluzione migliore. Puoi facilmente modificarli e ti servirà solo una rapida occhiata per vedere che tutto va bene. Se si opta per i file di proprietà, selezionare attentamente una posizione standard per loro e assegnare una variabile ambientale per il percorso.

Aiuta anche se hai un semplice test che verifica che tutto sia impostato correttamente. Ad esempio è ansible avere una pagina di test che visualizza i parametri di configurazione ed esegue alcuni test di base, come provare a connettersi al database o ai server remoti.

Il buon esempio di ciò che vuoi è usato in Seam o Grails (preso in prestito da Rails). Ci sono profili, di default tre: prod, dev, test, ma puoi definirne di più se vuoi.

Nel progetto Seam la compilazione viene eseguita da file Ant. Eeach Il file che il contenuto può variare è definito per ogni profilo, ad esempio origine dati, script SQL o file di proprietà.

import-dev.sql
import-prod.sql
import-test.sql

Quando il file ant viene eseguito con il profilo scelto, viene preso il file appropriato e il nome del profilo viene troncato da quel nome file.

Di seguito è riportato lo snippet di codice che puoi inserire nei target

  

URL JDBC, i nomi dei driver possono essere esternalizzati a file di proprietà (ovviamente con nomi di profilo come suffissi)

      

o i valori delle proprietà che puoi passare alla chiamata di formica dalla riga di comando. Questo è un breve esempio di ciò che è stato fatto in Seam.

Un’altra opzione è usare Maven . Nel modo migliore è fatto da proprietà e profili , ma è ansible utilizzare anche moduli separati per dividere la configurazione e creare altri moduli con funzionalità principali. Esempi tipici di casi d’uso di proprietà e profili di Maven sono la configurazione di esecuzione per più database, server di distribuzione ecc. È ancora più difficile quando si desidera creare la configurazione per diversi fornitori, ma per Maven questo non è un problema 🙂

Un ottimo esempio di utilizzo dei profili di esperti è il blog di Carlos Sanchez .

Per riassumere, raccomando caldamente di consultare Ant / Seam una parametrizzazione di Maven (profili). Queste soluzioni hanno un altro vantaggio: lo script ant o maven può essere eseguito nel server CI (come Hudson ) e consente di eseguire / test simultaneamente tutti i profili.

È ansible utilizzare il modello di configurazione del componente nella lingua scelta

È descritto nei libri POSA (penso che nel 4 ° volume)

(in java puoi usare il componente di configurazione commons ).

Ci sono alcuni modi possibili per avvicinarsi a questo:

  • usa i file di proprietà come fai tu, ma aggiungi un file “meta proprietà” che viene utilizzato per selezionare il file di proprietà utilizzato definendo una mappa tra un valore di ambiente (ad esempio localhost hostname) sul nome file della proprietà da caricare.

  • inserisci le tue proprietà in un database e definisci la connessione del database alle tabelle delle proprietà nel tuo server delle applicazioni come risorsa che viene rilevata dalla tua web-app.

  • non inserire i file di proprietà nel file .war o .ear, ma creare un archivio properties-deployhost.jar contenente i file di proprietà per host di destinazione. associare il file .jar appropriato all’app Web distribuita aggiungendola al percorso della class (ad esempio tramite librerie condivise nella configurazione del server delle applicazioni per app Web.)

Solo il primo di questi non richiede passaggi manuali aggiuntivi durante la distribuzione a spese di dover aggiornare l’origine della configurazione e creare nuovi file di distribuzione quando i sistemi di destinazione vengono rinominati.

Sono sicuro che molte varianti su questi e sul tuo approccio sono possibili, qual è la scelta migliore dipende dalla tua situazione.

Quello che facciamo funziona piuttosto bene.

All’avvio, i nostri programmi leggono un file di configurazione in un percorso hardcoded. Diciamo che è:

 /config/fun_prog/config.xml 

Ogni programma ha un diverso percorso hard coded (FunProgram è in fun_prog, Super Server è in sup_serv, qualunque cosa), quindi non dobbiamo preoccuparci che camminino l’uno sull’altro.

I file XML vengono letti da una piccola libreria di configurazione che abbiamo creato. Il file XML contiene le informazioni sulla connessione DB, in genere i dati di configurazione del server di posta, gli indirizzi e-mail per inviare notifiche, se deve funzionare in modalità test, URL di servizi esterni, ecc.

Quindi, quando abbiamo bisogno di apportare modifiche, copia il file di configurazione, modifica quello che vogliamo e riavvia il programma. Dato che abbiamo una configurazione standard del server, qualsiasi programma può essere distribuito su qualsiasi server semplicemente copiando questi file (e il necessario httpd.conf armeggiare).

Non è lussuoso, ma funziona molto bene. È estremamente semplice da comprendere, aggiungere nuove opzioni di configurazione, backup e modifica. Funziona su tutte le piattaforms (unix è ovvio, Windows traduce i percorsi che iniziano con / in c: \ quindi funziona anche senza modifiche).

Le nostre workstation eseguono fondamentalmente lo stesso software del server, solo con alcune modifiche in quel file di configurazione.

Si prega di dare un’occhiata a questo URL: http://issues.apache.org/jira/browse/CONFIGURATION-394

Il framework di configurazione che stiamo cercando è qualcosa in cima alla configurazione di Apache Commons e deve supportare problemi di concorrenza, problemi JMX e la maggior parte dei negozi (ad esempio file .properties, file .xml o PreferencesAPI).

Ciò che il team di weblogic fornisce su “Console di amministrazione” è interessante e attraverso di esso è ansible avere aggiornamenti transazionali (atomici) sulle configurazioni in modo che gli ascoltatori registrati vengano avvisati.

I ragazzi di Apache insistono sul fatto che questo progetto non rientra negli ambiti di Commons Configuration, forse!

Ho allegato un semplice framework di configurazione, guarda per favore.