Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

Ett av de största problemen vid utveckling och efterföljande drift av mikroservicer är korrekt och noggrant inställning av deras instanser. Jag tror att en ny ramverk kan hjälpa till med detta. microconfig.io. Den möjliggör en ganska elegant lösning på vissa rutinuppgifter vid inställning av applikationer.

Om du har många mikroservicer och varje av dem levereras med sin egen konfigurationsfil/er, är risken stor att fel kan inträffa i en av dessa, vilket kan vara svårt att upptäcka utan lämplig skicklighet och loggningssystem. Den huvudsakliga uppgiften som ramverket ställer sig är att minimera dubbletter av inställningsparametrar för instanser, vilket minskar risken för att införa fel.

Låt oss ta ett exempel. Anta att det finns en enkel applikation med en konfigurationsfil yaml. Detta kan vara vilken mikroservice som helst på vilket språk som helst. Låt oss se hur ramverket kan tillämpas på denna tjänst.

Men först, för större bekvämlighet, skapa ett tomt projekt i Idea IDE, efter att ha installerat microconfig.io-plugin:

Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

Vi konfigurerar uppstartskonfigurationen för plugin, vi kan använda standardkonfigurationen som på skärmbilden ovan.

Vår tjänst heter order, så i det nya projektet skapar vi en liknande struktur:

Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

I mappen med tjänstens namn placerar vi konfigurationsfilen — application.yaml. Alla mikroservicer körs i någon miljö, så förutom att skapa konfigurationsfilen för själva tjänsten, måste vi beskriva själva miljön: för detta skapar vi en mapp envs och lägger till en fil med namnet på vår arbetsmiljö. På så sätt kommer ramverket att skapa konfigurationsfiler för tjänster i miljön dev, eftersom detta parameter har ställts in i plugin-inställningarna.

Strukturen på filen dev.yaml kommer att vara ganska enkel:

mainorder:
    components:
         - order

Ramverket arbetar med konfigurationer som grupperas. För vår tjänst väljer vi ett namn för gruppen mainorder. Ramverket hittar varje sådan grupp av applikationer i miljöfilen och skapar konfigurationer för alla av dem som finns i motsvarande mappar.

I själva tjänstens inställningsfil order anger vi för tillfället bara en parameter:

spring.application.name: order

Låt oss nu starta plugin och den kommer att generera den nödvändiga konfigurationen av vår tjänst enligt den angivna sökvägen i egenskaperna:

Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

Det går även utan att installera plugin, bara genom att ladda ner distributionspaketet för ramverket och köra det från kommandoraden. Denna lösning passar för användning på byggserver.
Det är värt att notera att ramverket utmärkt förstår

property syntaxen, det vill säga vanliga property-filer som kan användas tillsammans med konfigurationerna. yaml Vi lägger till ytterligare en tjänst

payment och gör det samtidigt mer komplicerat. eureka: instance.preferIpAddress: true client: serviceUrl: defaultZone: http://192.89.89.111:6782/eureka/ server.port: 9999 spring.application.name: order db.url: 192.168.0.100
I order:

eureka:
 instance.preferIpAddress: true
 client:
   serviceUrl:
     defaultZone: http://192.89.89.111:6782/eureka/
server.port: 9998
spring.application.name: payments
db.url: 192.168.0.100

I och gör det samtidigt mer komplicerat.:

Det största problemet med dessa konfigurationer är förekomsten av en stor mängd kopia-och-klistra i konfigurationerna för tjänsterna. Låt oss se hur ramverket kan hjälpa oss att bli kvitt detta. Vi börjar med den mest uppenbara — förekomsten av konfigurationen

eureka i beskrivningen av varje mikrotjänst. Vi skapar en ny katalog med en inställningsfil och lägger till den nya konfigurationen i denna: Och vi lägger nu till raden

Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

Ramverket kommer automatiskt att hitta eureka-konfigurationen och kopiera den till varje tjänsts konfigurationsfiler, medan en separat eureka-konfiguration inte kommer att skapas eftersom vi inte anger den i miljöfilen #include eureka.

. Tjänsten dev.yamlVi kan också flytta databasinställningarna till en separat konfiguration genom att ändra import-raden till order:

#include eureka
server.port: 9999
spring.application.name: order
db.url: 192.168.0.100

Det är värt att notera att varje ändring vid regenerering av konfigurationsfiler övervakas av ramverket och placeras i en speciell fil bredvid huvudkonfigurationsfilen. Posten i dess logg ser ut så här: "Stored 1 property changes to #include eureka, oracle.

order/diff-application.yaml ". Detta möjliggör en snabb upptäckte av ändringar i stora konfigurationsfiler.Att flytta gemensamma delar av konfigurationen gör att vi kan bli av med mycket onödig kopia-och-klistra, men möjliggör inte flexibel skapelse av konfiguration för olika miljöer — våra tjänsters endpoint är unika och hårdkodade, vilket är dåligt. Låt oss försöka åtgärda detta.

En bra lösning skulle vara att hålla alla endpoints i en gemensam konfiguration som de andra kan hänvisa till. För detta har ramverket stöd för platshållare. Så här kommer konfigurationsfilen att ändras

... i beskrivningen av varje mikrotjänst. Vi skapar en ny katalog med en inställningsfil och lägger till den nya konfigurationen i denna::

 klient:
   serviceUrl:
     defaultZone: http://${endpoints@eurekaip}:6782/eureka/

Låt oss nu se hur denna platsfyllare fungerar. Systemet hittar komponenten med namnet endpoints och letar efter värdet eurekaip, varefter det sätts in i vår konfiguration. Men hur gör vi med olika miljöer? För detta ska vi skapa en inställningsfil av endpoints följande typ application.dev.yaml. Ramverket avgör självmant vilken miljö denna konfiguration tillhör baserat på filnamnets förlängning och laddar in den:

Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

Innehållet i dev-filen:

eurekaip: 192.89.89.111
dbip: 192.168.0.100

En liknande konfiguration kan vi skapa för portar av våra tjänster:

server.port: ${ports@order}.

Alla viktiga inställningar finns på ett ställe, vilket minskar risken för fel på grund av spridda parametrar i konfigurationsfiler.

Ramverket tillhandahåller många redan färdiga platshållare, till exempel kan man få namnet på katalogen där konfigurationsfilen finns och tilldela det:

#include eureka, oracle
server.port: ${ports@order}
spring.application.name: ${this@name}

Tack vare detta behöver vi inte ange applikationens namn i konfigurationen, utan kan också flytta det till en gemensam modul, till exempel till samma eureka:

klient:
   serviceUrl:
     defaultZone: http://${endpoints@eurekaip}:6782/eureka/
 spring.application.name: ${this@name}

Konfigurationsfilen order kortas ner till en rad:

#include eureka, oracle
server.port: ${ports@order}

Om någon inställning från föräldrakonfigurationen inte behövs kan vi ange den i vår konfiguration och just den kommer att tillämpas vid genereringen. Så om vi av någon anledning behöver ett unikt namn för tjänsten order, lämnar vi bara parametern spring.application.name.

Anta att vi behöver lägga till anpassade loggningsinställningar som lagras i en separat fil, till exempel, logback.xml. Vi ska skapa en separat grupp av inställningar för den:

Lätt hantering av mikroservicekonfigurationer med hjälp av microconfig.io

I den grundläggande konfigurationen anger vi för ramverket var det ska placera den önskade loggningsinställningsfilen med en platshållare @ConfigDir:

microconfig.template.logback.fromFile: ${logback@configDir}/logback.xml

I filen logback.xml konfigurerar vi de standardappen-drar som också kan innehålla platshållare, vilka ramverket kommer att ändra vid generering av konfigurationerna, till exempel:

logs/${this@name}.log

Genom att lägga till import av inställningar för tjänster logback, får vi automatiskt konfigurerad loggning för varje tjänst:

#include eureka, oracle, logback
server.port: ${ports@order}

Det är dags att bli mer bekant med alla tillgängliga platshållare i ramverket:

${this@env} — returnerar namnet på den aktuella miljön.
${…@name} — returnerar namnet på komponenten.
${…@configDir} — returnerar den fullständiga sökvägen till konfigurationskatalogen för komponenten.
${…@resultDir} — returnerar den fullständiga sökvägen till destinationkatalogen för komponenten (de erhållna filerna kommer att placeras i denna katalog).
${this@configRoot} — returnerar den fullständiga sökvägen till rotkatalogen för konfigurationslagret.

Systemet tillåter även att hämta miljövariabler, till exempel sökvägen till java:
${env@JAVA_HOME}
Eller, eftersom ramverket är skrivet i JAVA, kan vi hämta systemvariabler på liknande sätt som att anropa System::getProperty med en konstruktion av detta slag:
${system@os.name}
Det är värt att nämna stödet för utvidgningsspråket Spring EL. I konfigurationen kan liknande uttryck användas:

connection.timeoutInMs: #{5 * 60 * 1000}
datasource.maximum-pool-size: #{${this@datasource.minimum-pool-size} + 10} 

och lokala variabler kan användas i konfigurationsfiler med uttrycket #var:

#var feedRoot: ${system@user.home}/feed
folder:
 root: ${this@feedRoot}
 success: ${this@feedRoot}/archive
 error: ${this@feedRoot}/error

På så sätt utgör ramverket ett ganska kraftfullt verktyg för fin och flexibel justering av konfigurationerna för mikrotjänster. Ramverket utför sin huvuduppgift utmärkt — att eliminera kopiering i inställningarna, konsolidera inställningar och därmed minimera möjliga fel, samtidigt som det möjliggör enkel kombination av konfigurationer och förändringar för olika miljöer.

Om du är intresserad av detta ramverk rekommenderar jag att du besöker dess officiella sida och bekantar dig med hela dokumentationen, eller gräva lite i källkoden ). Ett typiskt exempel på användning:.

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster