Java-webapplicatieconfiguratiepatronen

Zijn er patronen of best practices die kunnen worden gebruikt om het wijzigen van configuratieprofielen voor Java-webapplicaties in meerdere omgevingen te vereenvoudigen. bijv. JDBC-URL’s, SOAP-eindpunten, enz.

Als een beetje achtergrond om mijn vraag te verduidelijken, werk ik met verschillende grote Java-webapplicaties die tijdens een bepaalde releasecyclus door 6 verschillende omgevingen bewegen; ontwikkeling, integratie, QA, prestaties en uiteindelijk worden geïmplementeerd op meerdere productieservers. In elke omgeving moet de configuratie worden gewijzigd. Op dit moment worden de meeste configuratiewijzigingen voor elke implementatie handmatig uitgevoerd, wat zowel tijdrovend als foutgevoelig is.
Is er een manier om de handmatige tussenkomst uit dit proces te halen?


Antwoord 1, autoriteit 100%

Het verbaast me dat niemand de Jakarta Commons Configuration API (http://commons.apache.org /configuratie/) om deze vraag te beantwoorden. Hiermee kunt u een hiërarchie van bestanden hebben (of andere configuratiebronnen zoals XML, JNDI, JDBC, enz.). Dat is waar Jeremy Seghi het over had en het geeft je een goede manier om zowel standaardinstellingen als lokale overschrijvingen te hebben.

Het beste is dat het een geteste werkende oplossing is, zodat u niet zelf iets hoeft te maken.


Antwoord 2, autoriteit 48%

Ik werk de laatste tijd meer met .NET, dus mijn Java is redelijk roestig. Ik ben er vrij zeker van dat dit in elke taal zou werken met een beetje tweaken.

We gebruiken een uitbreiding van het .NET-configuratiesysteem waarmee we omgevings- en/of applicatiespecifieke instellingen kunnen gebruiken in combinatie met een meer globale configuratie. Het configuratiesysteem gebruikt een algemene instelling om elke machine te identificeren als dev, bèta of productie (de standaardinstelling). Een set bestanden die in volgorde zijn geladen, en de instelling van het laatste bestand heeft voorrang op elke instelling die is gedefinieerd in een eerder geladen bestand. Bestanden worden in de volgende volgorde geladen:

  1. Algemene instellingen
  2. Toepassingsspecifieke instellingen
  3. Toepassingsspecifieke omgeving overschrijft

Alle bestanden staan ​​onder bronbeheer en aangezien de omgeving is gedefinieerd op de machine waarop de toepassing draait; aangezien het geen toegang heeft tot de “bèta”-configuratie tenzij de machineconfiguratie het als “bèta” identificeert, kunnen we alle configuratiebestanden promoten zonder bang te hoeven zijn onze productietoepassing per ongeluk naar een dev-database te verwijzen.


Antwoord 3, autoriteit 35%

Hier zijn enkele mogelijke praktijken die ik heb gebruikt of ben tegengekomen. Het combineren hiervan is in de praktijk meestal nodig.

De variabele waarden in configuraties vervangen tijdens het bouwen

Hier is een voorbeeld van hoe dit kan worden gedaan met Apache Ant. Ant-eigenschappen (${var.name}) kunnen worden beheerd met de buildconfiguratiebestanden:

<filterset id="variables.to.replace">
    <filter token="APPNAME" value="${app.name}"/>
    <filter token="WEBAPP-PATH" value="${webapp.path}"/>
    <filter token="ENCRYPT-ALGORITHM" value="${encrypt.algorithm}"/>
    <filter token="ERROR-MAILTO" value="${error.mailTo}"/>
    <!--...-->
</filterset>
<!-- Then, when building & copying the conf, replace the variables: -->
<copy todir="${properties.target.dir}">
    <!-- env specific conf files -->
    <fileset dir="${basedir}/env/${run.env}/webapp/WEB-INF/classes" />
    <filterset refid="variables.to.replace"/>
</copy>

Het goede is dat je tijdens het bouwen een goede controle krijgt over de verschillende configuraties. Wat slecht is, is dat het systeem de neiging heeft om erg complex en moeilijk te onderhouden te worden als je deze methode op grote schaal gebruikt voor een groot aantal verschillende configuraties. Ook het bouwen van de configuratiebestanden betekent langzamere ontwikkelingscycli.

De variabelen van conf inside war vervangen bij het opstarten van de webapp

Dit is wat ik gewoonlijk doe als ik Spring Framework gebruik, zelfs als er maar één mogelijke configuratie is, waarbij ik de voordelen krijg van het scheiden van zorgen. Met Spring kunt u de conf-waarden laten vervangen door PlaceholderPropertyConfigurer in Spring-context bij het opstarten van de webapp. In dit geval moet je hoe dan ook de juiste configuratie kiezen, die bijvoorbeeld kan worden geconfigureerd tijdens de bouwtijd.

Vergeleken met de vervanging van de bouwtijd, is het indien nodig gemakkelijker om de waarden tijdelijk te manipuleren in een niet-gecomprimeerde webapp. Natuurlijk moet de webapp opnieuw worden opgestart als u iets wijzigt, en de handmatige wijzigingen blijven niet behouden bij herimplementaties van webapps. Spring is ook beperkt tot de Spring-context, dus dit werkt niet bijv in web.xml(maar het hebben van variabelen in web.xml zou hoe dan ook moeten worden vermeden vanwege de beperkingen).

De lokale conf uit een vooraf gedefinieerd bestand lezen

Deze aanpak is waarschijnlijk de gemakkelijkste om in te stellen: bedenk gewoon een configuratiebestandspad, b.v. $HOME/mywebapp/conf.propertiesen laat je webapp het op de een of andere manier lezen bij het opstarten.

Het goede hieraan is dat je je geen zorgen hoeft te maken over de conf bij het bouwen/implementeren van de webapp. Hoe dan ook, je zou een aantal verstandige conf-standaardinstellingen moeten hebben die dan kunnen worden overschreven door de lokale conf.

De conf in een database hebben

Dit is de meest flexibele oplossing voor het overschrijven van conf-parameters, maar kan in sommige gevallen ook ingewikkeld worden. De conf in een tabel met nameen valuekolommen zou in de meeste gevallen moeten werken.

Natuurlijk kunt u de JDBC-verbindings-URL’s niet configureren in een databasetabel, maar dit is een goede oplossing voor eenvoudige tekstuele/numerieke conf die de werking van de webapp beïnvloedt nadat de db-verbinding is ingesteld. Om prestatieverlies te voorkomen, moet u ervoor zorgen dat u de conf op de een of andere manier in de cache plaatst als deze vaak wordt gebruikt.

Extra oefeningen

Zoals aangegeven door kgiannakakis, helpt het ook om een ​​of andere configuratiediagnosepagina voor uw app op te zetten.


Antwoord 4, autoriteit 19%

Dit zal sterk afhangen van de opties die de webtoepassingsservers u geven. We hebben meerdere omgevingen voor JBoss met verschillende JDBC-URL’s, de JNDI-naam blijft hetzelfde op alle servers, alleen de configuratie op de lokale instantie verandert, dus er gaat niets mis van build tot build.

Ik denk dat het korte antwoord is dat de beste werkwijze is om de configuraties te externaliseren en een goed bestand op zijn plaats te houden met de juiste instellingen voor elke server, en de web-app die configuratie te laten lezen. De exacte aard van het externaliseren en lezen zal afhangen van de specifieke configuratie en applicatieserver.

EDIT: deze configuraties bestaan ​​niet als onderdeel van de oorlog (oor in ons geval), op die manier worden ze niet overschreven.


Antwoord 5, autoriteit 6%

Bewaar eerst alle configuratie-instellingen die vaak veranderen op één plek. Het is echt moeilijk als u JNDI moet instellen, databasewaarden moet bewerken en eigenschappenbestanden moet wijzigen om de configuratie te voltooien. Geef de voorkeur aan het medium dat het gemakkelijkst te bewerken is en ook gemakkelijker te controleren is of alles goed is ingesteld. Ik zou zeggen dat eigendomsbestanden de beste oplossing zijn. Je kunt ze gemakkelijk bewerken en je hoeft ze alleen maar even door te kijken om te zien dat alles in orde is. Kiest u voor eigenschappenbestanden, kies dan zorgvuldig een standaardlocatie daarvoor en wijs een omgevingsvariabele toe aan het pad.

Het helpt ook als je een eenvoudige test hebt die controleert of alles goed is ingesteld. U kunt bijvoorbeeld een testpagina hebben die de configuratieparameters weergeeft en enkele basistests uitvoert, zoals proberen verbinding te maken met een database of externe servers.


Antwoord 6, autoriteit 3%

Wat we doen, werkt redelijk goed.

Bij het opstarten lezen onze programma’s een configuratiebestand in een hardcoded pad. Laten we zeggen dat het is:

/config/fun_prog/config.xml

Elk programma heeft een ander hard gecodeerd pad (FunProgram bevindt zich in fun_prog, Super Server is in sup_serv, wat dan ook), dus we hoeven ons geen zorgen te maken dat ze over elkaar heen lopen.

De XML-bestanden worden gelezen door een kleine configuratiebibliotheek die we hebben gemaakt. Het XML-bestand bevat de DB-verbindingsinformatie, meestal configuratiegegevens van de mailserver, e-mailadressen waarnaar meldingen moeten worden verzonden, of het in testmodus moet werken, URL’s van externe services, enz.

Dus als we wijzigingen moeten aanbrengen, kopiëren we het configuratiebestand, bewerken we wat we willen en herstarten we het programma. Omdat we een standaard serverconfiguratie hebben, kan elk programma op elke server worden geïmplementeerd door deze bestanden gewoon te kopiëren (en het nodige httpd.conf-sleutelen).

Het is niet luxueus, maar het werkt erg goed. Het is uiterst eenvoudig te begrijpen, nieuwe configuratie-opties toe te voegen, back-ups te maken en te bewerken. Werkt op alle platforms (unix is ​​duidelijk, Windows vertaalt paden die beginnen met / in c:\ dus ook daar werkt het zonder bewerkingen).

Onze werkstations draaien in principe dezelfde software als de server, alleen met een paar wijzigingen in dat configuratiebestand.


Antwoord 7, autoriteit 3%

Het goede voorbeeld wat je zoekt wordt gebruikt in Seamof Grails (geleend van Rails). Er zijn profielen, standaard drie: prod, dev, test, maar je kunt er meer definiëren als je wilt.

In Seam wordt het project gebouwd door Ant-bestanden. Elk bestand waarvan de inhoud kan variëren, wordt gedefinieerd voor elk profiel, b.v. gegevensbron, sql-scripts of eigenschappenbestanden.

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

Als het ant-bestand wordt uitgevoerd met het gekozen profiel, wordt het juiste bestand genomen en wordt de profielnaam van die bestandsnaam afgekapt.

Hieronder staat een codefragment dat u in uw doelen kunt plaatsen

<copy tofile="${war.dir}/WEB-INF/classes/import.sql" 
      file="${basedir}/resources/import-${profile}.sql"/>

JDBC-url, stuurprogrammanamen kunnen worden geëxternaliseerd naar eigenschappenbestanden (uiteraard met profielnamen als achtervoegsels)

<filterset id="persistence">
     <filter token="transactionManagerLookupClass" value="${transactionManagerLookupClass}"/>
<copy tofile="${war.dir}/WEB-INF/classes/META-INF/persistence.xml" 
     file="${basedir}/resources/META-INF/persistence-${profile}.xml">
     <filterset refid="persistence"/>
</copy>

of waarden van eigenschappen die u kunt doorgeven aan ant build-oproep vanaf de opdrachtregel. Dit is een kort voorbeeld van wat er in Seam gedaan is.

Een andere optie is om Mavente gebruiken. Op een maven manier gedaan door eigenschappen en door profielen, maar u kunt ook afzonderlijke modules gebruiken om de configuratie te splitsen en andere modules met hoofdfunctionaliteit te maken. Typische use case-voorbeelden van maven-eigenschappen en profielen zijn uitvoeringsconfiguratie voor meerdere databases, implementatieservers enz. Het is nog moeilijker wanneer u configuraties voor verschillende leveranciers wilt maken, maar voor Maven is dat geen probleem 🙂

Een goed voorbeeld van het gebruik van maven-profielen is dit postformulier Carlos Sanchez-blog.

Samenvattend raad ik ten zeerste aan om de parametrisatie van Ant/Seam en Maven (profielen) op te zoeken. Die oplossingen hebben nog een ander voordeel: het ant- of maven-script kan worden uitgevoerd op de CI-server (zoals Hudson) en laten uitvoeren /test tegelijkertijd al je profielen.


Antwoord 8, autoriteit 3%

U kunt het componentconfiguratiepatroon gebruiken in uw taal naar keuze

Het wordt beschreven in de POSA-boeken (ik denk dat in het 4e deel)

(in java kun je de component commons-configurationgebruiken).


Antwoord 9

Er zijn een paar mogelijke manieren om dit aan te pakken:

  • Gebruik onroerendgoedbestanden zoals jij, maar voeg een “meta-eigenschappen” toe die wordt gebruikt om het eigenschapsbestand te selecteren dat wordt gebruikt door een kaart te definiëren tussen een omgevingwaarde (bijvoorbeeld LocalHost-hostnaam) op de naam van het eigendombestandsnaam belasting.

  • Zet uw eigenschappen in een database en definieer de databaseverbinding met de eigenschappenstabellen in uw toepassingsserver als resource dat wordt opgehaald door uw web-app.

  • Plaats de vastgoedbestanden niet in uw .war of .ear, maar maak een eigenschappen-deployhost.jar-archieven met de vastgoedbestanden per doelhost. Bind het juiste .jar-bestand aan de ingezette web-app door het toe te voegen aan het klassenpad (bijvoorbeeld via gedeelde bibliotheken in de configuratie van de applicatieserver per web-app.)

Alleen de eerste hiervan heeft geen extra handmatige stappen nodig bij het implementeren ten koste van het hebben van uw configuratiebron en het bouwen van nieuwe implementeerbestanden wanneer uw doelsystemen worden hernoemd.

Ik weet zeker dat veel varianten op deze en uw aanpak mogelijk zijn, wat is de beste keuze, hangt af van uw situatie.


Antwoord 10

Bekijk deze URL: http://issues.apache.org / Jira / Bladeren / Configuratie-394

Het configuratiekader waarnaar we op zoek zijn, is er iets bovenop Apache Commons-configuratie en moet rekening houden met concurrency-problemen, JMX-problemen en de meeste winkels (E.g .Properties-bestand, .xml-bestanden of preferencesapi).

Welk Weblogic Team biedt op ‘Administration Console’, die er doorheen kunt, kunt u transactionele (atomaire) updates over configuraties hebben, zodat geregistreerde luisteraars zijn aangemeld.

De Apache-jongens staan ​​erop dat dit project uit scopes van Commons-configuratie is, misschien!

Ik heb een eenvoudig configuratiekader bijgevoegd, kijk alsjeblieft.

Other episodes