Twaalf-factor methodologie in een Spring Boot Microservice

1. Overzicht

In deze tutorial zullen we de twaalf-factor-app-methodologie begrijpen.

We zullen ook begrijpen hoe u een microservice kunt ontwikkelen met behulp van Spring Boot. In het proces zullen we zien hoe we de twaalffactormethodologie kunnen toepassen om een ​​dergelijke microservice te ontwikkelen.

2. Wat is de twaalffactormethode?

De twaalffactormethode is een set van twaalf best practices om applicaties te ontwikkelen die zijn ontwikkeld om als een service te worden uitgevoerd. Dit werd oorspronkelijk opgesteld door Heroku voor applicaties die als services op hun cloudplatform werden geïmplementeerd, in 2011. In de loop van de tijd is dit generiek genoeg gebleken voor elke software-as-a-service (SaaS) -ontwikkeling.

Dus wat bedoelen we met software-as-a-service? Traditioneel ontwerpen, ontwikkelen, implementeren en onderhouden we softwareoplossingen om er bedrijfswaarde uit te halen. Maar we hoeven niet per se aan dit proces deel te nemen om hetzelfde resultaat te bereiken. Het berekenen van de toepasselijke belasting is bijvoorbeeld in veel domeinen een generieke functie.

Nu kunnen we besluiten om deze dienst zelf te bouwen en te beheren of zich abonneren op een commercieel serviceaanbod. Zo'n serviceaanbiedingen zijn wat we kennen als software-as-a-service.

Hoewel software-as-a-service geen enkele beperking oplegt aan de architectuur waarop het is ontwikkeld; het is best handig om enkele best practices toe te passen.

Als we onze software zo ontwerpen dat deze modulair, draagbaar en schaalbaar is op moderne cloudplatforms, is dat redelijk geschikt voor ons serviceaanbod. Dit is waar de twaalf-factor-methodologie helpt. We zullen ze later in de tutorial in actie zien.

3. Microservice met Spring Boot

Microservice is een architecturale stijl om software te ontwikkelen als losjes gekoppelde services. De belangrijkste vereiste hier is dat de diensten moeten worden georganiseerd rond de grenzen van het bedrijfsdomein. Dit is vaak het moeilijkste deel om te identificeren.

Bovendien heeft een service hier de enige autoriteit over zijn gegevens en stelt hij activiteiten bloot aan andere services. Communicatie tussen services verloopt doorgaans via lichtgewicht protocollen zoals HTTP. Dit resulteert in onafhankelijk inzetbare en schaalbare diensten.

Nu zijn microservice-architectuur en software-as-a-service niet meer van elkaar afhankelijk. Maar het is niet moeilijk om dat te begrijpen, wanneer het ontwikkelen van software-as-a-service, waarbij gebruik wordt gemaakt van de microservicearchitectuur, is behoorlijk voordelig. Het helpt om veel doelen te bereiken die we eerder bespraken, zoals modulariteit en schaalbaarheid.

Spring Boot is een applicatieframework op basis van Spring dat veel van de standaard wegneemt bij het ontwikkelen van een bedrijfsapplicatie. Het geeft ons een zeer eigenzinnig maar flexibel platform om microservices te ontwikkelen. Voor deze zelfstudie gebruiken we Spring Boot om een ​​microservice te leveren met behulp van de twaalffactormethode.

4. Twaalf-factorenmethodologie toepassen

Laten we nu een eenvoudige applicatie definiëren die we zullen proberen te ontwikkelen met de tools en praktijken die we zojuist hebben besproken. We houden allemaal van films kijken, maar het is een uitdaging om bij te houden welke films we al hebben gezien.

Wie wil er nu een film beginnen en deze later verlaten? Wat we nodig hebben, is een eenvoudige service om films op te nemen en op te vragen die we hebben bekeken:

Dit is een vrij eenvoudige en standaard microservice met een datastore en REST-eindpunten. We moeten een model definiëren dat ook naar persistentie zal verwijzen:

@Entity public class Movie {@Id privé Lange id; private String-titel; privé String jaar; private String-beoordeling; // getters en setters}

We hebben een JPA-entiteit gedefinieerd met een id en een paar andere attributen. Laten we nu eens kijken hoe de REST-controller eruitziet:

@RestController openbare klasse MovieController {@Autowired privé MovieRepository movieRepository; @GetMapping ("/ movies") openbare lijst retrieveAllStudents () {return movieRepository.findAll (); } @GetMapping ("/ movies / {id}") openbare Movie retrieveStudent (@PathVariable Lange id) {retourneer movieRepository.findById (id) .get (); } @PostMapping ("/ movies") openbaar Lang createStudent (@RequestBody Movie film) {return movieRepository.save (film) .getId (); }}

Dit dekt de basis van onze eenvoudige service. We zullen de rest van de toepassing doornemen terwijl we bespreken hoe we de twaalf-factormethodologie implementeren in de volgende subsecties.

4.1. Codebase

De eerste best practice van twaalf-factor-apps is om deze bij te houden in een versiebeheersysteem. Git is het meest populaire versiebeheersysteem dat tegenwoordig wordt gebruikt en is bijna alomtegenwoordig. Het principe stelt dat een app moet worden bijgehouden in een enkele coderepository en mag die repository niet delen met andere apps.

Spring Boot biedt veel handige manieren om een ​​applicatie op te starten, inclusief een opdrachtregelprogramma en een webinterface. Zodra we de bootstrap-applicatie hebben gegenereerd, kunnen we deze converteren naar een git-repository:

git init

Deze opdracht moet worden uitgevoerd vanuit de root van de applicatie. De applicatie bevat in dit stadium al een .gitignore-bestand dat effectief voorkomt dat gegenereerde bestanden versie-gecontroleerd worden. We kunnen dus meteen een eerste commit maken:

git add. git commit -m "De bootstrap van de applicatie toevoegen."

Ten slotte kunnen we een afstandsbediening toevoegen en onze commits naar de afstandsbediening pushen als we dat willen (dit is geen strikte vereiste):

git remote add origin //github.com//12-factor-app.git git push -u origin master

4.2. Afhankelijkheden

Vervolgens de Twaalf-factor-app moet altijd expliciet al zijn afhankelijkheden aangeven. We moeten dit doen met behulp van een manifest van een afhankelijkheidsverklaring. Java heeft meerdere tools voor afhankelijkheidsbeheer, zoals Maven en Gradle. We kunnen een van hen gebruiken om dit doel te bereiken.

Onze eenvoudige applicatie is dus afhankelijk van een paar externe bibliotheken, zoals een bibliotheek om REST API's te vergemakkelijken en om verbinding te maken met een database. Laten we eens kijken hoe we ze declaratief kunnen definiëren met Maven.

Maven vereist dat we de afhankelijkheden van een project beschrijven in een XML-bestand, meestal bekend als Project Object Model (POM):

  org.springframework.boot spring-boot-starter-web com.h2database h2 runtime 

Hoewel dit er duidelijk en eenvoudig uitziet, hebben deze afhankelijkheden meestal andere transitieve afhankelijkheden. Dit bemoeilijkt het tot op zekere hoogte, maar helpt ons ons doel te bereiken. Nu heeft onze applicatie geen directe afhankelijkheid die niet expliciet wordt beschreven.

4.3. Configuraties

Een applicatie heeft doorgaans veel configuraties, waarvan sommige kunnen variëren tussen implementaties, terwijl andere hetzelfde blijven.

In ons voorbeeld hebben we een permanente database. We hebben het adres en de inloggegevens van de database nodig om verbinding te maken. Dit verandert waarschijnlijk tussen implementaties.

Een twaalf-factor-app moet al dergelijke configuraties die variëren tussen implementaties, extern maken. De aanbeveling hier is om omgevingsvariabelen te gebruiken voor dergelijke configuraties. Dit leidt tot een zuivere scheiding van configuratie en code.

Spring biedt een configuratiebestand waarin we dergelijke configuraties kunnen declareren en aan omgevingsvariabelen kunnen koppelen:

spring.datasource.url = jdbc: mysql: // $ {MYSQL_HOST}: $ {MYSQL_PORT} / films spring.datasource.username = $ {MYSQL_USER} spring.datasource.password = $ {MYSQL_PASSWORD}

Hier hebben we de database-URL en referenties gedefinieerd als configuraties en hebben we de werkelijke waarden toegewezen die uit de omgevingsvariabele moeten worden gehaald.

Op Windows kunnen we de omgevingsvariabele instellen voordat we de applicatie starten:

set MYSQL_HOST = localhost set MYSQL_PORT = 3306 set MYSQL_USER = films set MYSQL_PASSWORD = wachtwoord

We kunnen een configuratiebeheertool zoals Ansible of Chef gebruiken om dit proces te automatiseren.

4.4. Ondersteunende diensten

Backing-services zijn services waarvan de toepassing afhankelijk is voor gebruik. Bijvoorbeeld een database of een message broker. Een twaalf-factor-app moet al dergelijke ondersteuningsservices behandelen als gekoppelde bronnen. Wat dit in feite betekent, is dat er geen codewijziging nodig is om een ​​compatibele ondersteuningsservice om te wisselen. De enige verandering zou in configuraties moeten zijn.

In onze applicatie hebben we MySQL als ondersteunende service gebruikt om persistentie te bieden.

Spring JPA maakt de code vrij agnostisch voor de daadwerkelijke databaseprovider. We hoeven alleen een repository te definiëren die alle standaardbewerkingen biedt:

@Repository openbare interface MovieRepository breidt JpaRepository uit {}

Zoals we kunnen zien, is dit niet rechtstreeks afhankelijk van MySQL. Spring detecteert het MySQL-stuurprogramma op het klassenpad en biedt dynamisch een MySQL-specifieke implementatie van deze interface. Bovendien haalt het andere details rechtstreeks uit configuraties.

Dus als we moeten veranderen van MySQL naar Oracle, hoeven we alleen maar de driver in onze afhankelijkheden te vervangen en de configuraties te vervangen.

4.5. Bouwen, vrijgeven en uitvoeren

De twaalffactormethode scheidt strikt het proces van het converteren van codebase naar een actieve applicatie als drie verschillende fasen:

  • Build Stage: hier nemen we de codebase, voeren statische en dynamische controles uit en genereren vervolgens een uitvoerbare bundel zoals een JAR. Met een tool als Maven is dit vrij triviaal:
 mvn clean compileertestpakket
  • Release Stage: dit is de fase waarin we de uitvoerbare bundel nemen en deze combineren met de juiste configuraties. Hier kunnen we Packer gebruiken met een provisioner zoals Ansible om Docker-images te maken:
 packer build application.json
  • Fase uitvoeren: Ten slotte is dit de fase waarin we de applicatie uitvoeren in een doeluitvoeringsomgeving. Als we Docker gebruiken als de container om onze applicatie vrij te geven, kan het draaien van de applicatie eenvoudig genoeg zijn:
 docker run --name -it 

Ten slotte hoeven we deze fasen niet per se handmatig uit te voeren. Dit is waar Jenkins goed van pas komt met hun declaratieve pijplijn.

4.6. Processen

Van een twaalf-factor-app wordt verwacht dat deze in een uitvoeringsomgeving wordt uitgevoerd als stateless processen. Met andere woorden, ze kunnen geen permanente status lokaal opslaan tussen verzoeken. Ze kunnen persistente gegevens genereren die moeten worden opgeslagen in een of meer stateful backup-services.

In het geval van ons voorbeeld hebben we meerdere eindpunten blootgelegd. Een verzoek op een van deze eindpunten is volledig onafhankelijk van een eerder gedaan verzoek. Als we bijvoorbeeld gebruikersverzoeken in het geheugen bijhouden en die informatie gebruiken om aan toekomstige verzoeken te voldoen, is dit in strijd met een twaalf-factor-app.

Daarom legt een twaalf-factor-app geen beperking op zoals plakkerige sessies. Dit maakt zo'n app zeer draagbaar en schaalbaar. In een cloud-uitvoeringsomgeving die geautomatiseerd schalen biedt, is het nogal een wenselijk gedrag van applicaties.

4.7. Poortbinding

Een traditionele webapplicatie in Java wordt ontwikkeld als een WAR- of webarchief. Dit is typisch een verzameling Servlets met afhankelijkheden, en het verwacht een conforme containerruntime zoals Tomcat. Een twaalf-factor-app daarentegen verwacht zo'n runtime-afhankelijkheid niet. Het is volledig op zichzelf staand en vereist alleen een uitvoeringsruntime zoals Java.

In ons geval hebben we een applicatie ontwikkeld met Spring Boot. Spring Boot biedt ons, afgezien van vele andere voordelen, een standaard embedded applicatieserver. Daarom kan de JAR die we eerder met Maven hebben gegenereerd, volledig in elke omgeving worden uitgevoerd door een compatibele Java-runtime te hebben:

java -jar applicatie.jar

Hier stelt onze eenvoudige applicatie zijn eindpunten bloot via een HTTP-binding aan een specifieke poort zoals 8080. Bij het starten van de applicatie zoals we hierboven deden, zou het mogelijk moeten zijn om toegang te krijgen tot de geëxporteerde services zoals HTTP.

Een applicatie kan meerdere services zoals FTP of WebSocket exporteren door aan meerdere poorten te binden.

4.8. Gelijktijdigheid

Java biedt Draad als een klassiek model om concurrency in een applicatie af te handelen. Threads zijn als lichtgewicht processen en vertegenwoordigen meerdere uitvoeringspaden in een programma. Threads zijn krachtig, maar hebben beperkingen in termen van hoeveel het een toepassingsschaal kan helpen.

De twaalffactormethode suggereert dat apps voor schaalvergroting afhankelijk zijn van processen. Wat dit in feite betekent, is dat applicaties moeten worden ontworpen om de werklast over meerdere processen te verdelen. Individuele processen zijn echter vrij om gebruik te maken van een concurrency-model zoals Draad intern.

Een Java-applicatie krijgt bij het opstarten een enkel proces dat is gebonden aan de onderliggende JVM. Wat we effectief nodig hebben, is een manier om meerdere instances van de applicatie te starten met een intelligente verdeling van de belasting ertussen. Omdat we onze applicatie al hebben verpakt als een Docker-container, is Kubernetes een logische keuze voor dergelijke orkestratie.

4.9. Wegwerpbaarheid

Aanvraagprocessen kunnen met opzet of door een onverwachte gebeurtenis worden afgesloten. In elk geval, een twaalf-factor-app zou er gracieus mee om moeten gaan. Met andere woorden, een aanvraagprocedure moet volledig wegwerpbaar zijn zonder ongewenste neveneffecten. Bovendien moeten processen snel starten

In onze applicatie is een van de eindpunten bijvoorbeeld het maken van een nieuw databaserecord voor een film. Nu kan een toepassing die een dergelijk verzoek verwerkt, onverwachts crashen. Dit heeft echter geen invloed op de staat van de applicatie. Wanneer een klant hetzelfde verzoek opnieuw verzendt, mag dit niet resulteren in dubbele records.

Samenvattend zou de applicatie idempotent services moeten tonen. Dit is een ander zeer wenselijk kenmerk van een service die is bedoeld voor cloudimplementaties. Dit geeft de flexibiliteit om op elk moment en zonder andere overwegingen nieuwe services te stoppen, verplaatsen of draaien.

4.10. Dev / Prod-pariteit

Het is typerend voor applicaties die op lokale machines worden ontwikkeld, in een aantal andere omgevingen worden getest en uiteindelijk in productie worden genomen. Het is vaak het geval wanneer deze omgevingen verschillend zijn. Het ontwikkelingsteam werkt bijvoorbeeld op Windows-machines, terwijl productie-implementatie plaatsvindt op Linux-machines.

De twaalffactormethodologie stelt voor om de kloof tussen ontwikkel- en productieomgeving zo klein mogelijk te houden. Deze hiaten kunnen het gevolg zijn van lange ontwikkelingscycli, verschillende betrokken teams of verschillende gebruikte technologiestacks.

Nu overbruggen technologie zoals Spring Boot en Docker deze kloof automatisch grotendeels. Van een gecontaineriseerde applicatie wordt verwacht dat deze zich hetzelfde gedraagt, ongeacht waar we deze uitvoeren. We moeten dezelfde ondersteuningsservices gebruiken - zoals de database - ook.

Bovendien moeten we over de juiste processen beschikken, zoals continue integratie en levering, om deze kloof verder te overbruggen.

4.11. Logboeken

Logboeken zijn essentiële gegevens die een applicatie tijdens zijn levensduur genereert. Ze bieden onschatbare inzichten in de werking van de applicatie. Typisch kan een applicatie logboeken genereren op meerdere niveaus met verschillende details en output ii in meerdere verschillende formaten.

Een twaalf-factor-app onderscheidt zichzelf echter van het genereren en verwerken van logboeken. Voor zo'n app zijn logboeken niets anders dan een op tijd geordende stroom van gebeurtenissen. Het schrijft deze gebeurtenissen alleen naar de standaarduitvoer van de uitvoeringsomgeving. Het vastleggen, opslaan, beheren en archiveren van een dergelijke stream moet worden afgehandeld door de uitvoeringsomgeving.

Hiervoor hebben we nogal wat tools tot onze beschikking. Om te beginnen kunnen we SLF4J gebruiken om logboekregistratie abstract binnen onze applicatie af te handelen. Bovendien kunnen we een tool zoals Fluentd gebruiken om de stroom logboeken van applicaties en ondersteunende services te verzamelen.

Dit kunnen we in Elasticsearch invoeren voor opslag en indexering. Ten slotte kunnen we betekenisvolle dashboards genereren voor visualisatie in Kibana.

4.12. Beheerprocessen

Vaak moeten we eenmalige taken of routineprocedures uitvoeren met onze applicatiestatus. Bijvoorbeeld het repareren van slechte records. Nu zijn er verschillende manieren waarop we dit kunnen bereiken. Omdat we het misschien niet vaak nodig hebben, kunnen we een klein script schrijven om het apart van een andere omgeving uit te voeren.

Nu, de twaalf-factor-methodologie suggereert sterk om dergelijke admin-scripts samen met de applicatiecodebase te houden. Daarbij moet het dezelfde principes volgen als we toepassen op de hoofdcodebase van de applicatie. Het is ook raadzaam om een ​​ingebouwde REPL-tool van de uitvoeringsomgeving te gebruiken om dergelijke scripts op productieservers uit te voeren.

Hoe zaaien we in ons voorbeeld onze applicatie met de reeds bekeken films tot nu toe? Hoewel we ons lieve kleine eindpunt kunnen gebruiken, maar dat lijkt misschien onpraktisch. Wat we nodig hebben, is een script om een ​​eenmalige belasting uit te voeren. We kunnen een kleine Java-functie schrijven om een ​​lijst met films uit een bestand te lezen en ze in batch op te slaan in de database.

Bovendien kunnen we Groovy geïntegreerd met Java-runtime gebruiken om dergelijke processen te starten.

5. Praktische toepassingen

Dus nu hebben we alle factoren gezien die worden gesuggereerd door de twaalffactormethode. Een applicatie ontwikkelen om een Twaalf-factor-app heeft zeker zijn voordelen, vooral als we ze als services in de cloud willen inzetten. Maar, net als alle andere richtlijnen, raamwerken, patronen, moeten we ons afvragen: is dit een zilveren kogel?

Eerlijk gezegd beweert geen enkele methodologie in softwareontwerp en -ontwikkeling een wondermiddel te zijn. De twaalffactormethode is geen uitzondering. Terwijl sommige van deze factoren zijn vrij intuïtief, en hoogstwaarschijnlijk doen we ze al, andere zijn mogelijk niet op ons van toepassing. Het is essentieel om deze factoren tegen de achtergrond van onze doelstellingen te evalueren en vervolgens een verstandige keuze te maken.

Het is belangrijk op te merken dat al deze factoren dat zijn daar om ons te helpen een applicatie te ontwikkelen die modulair, onafhankelijk, draagbaar, schaalbaar en waarneembaar is. Afhankelijk van de toepassing kunnen we ze misschien op andere manieren beter bereiken. Het is ook niet nodig om alle factoren samen over te nemen, zelfs enkele hiervan kan ons beter maken dan we waren.

Ten slotte zijn deze factoren vrij eenvoudig en elegant. Ze zijn belangrijker in een tijd waarin we eisen dat onze applicaties een hogere doorvoer en lagere latency hebben met vrijwel geen downtime en uitval. Door deze factoren toe te passen, hebben we vanaf het begin de juiste start. Gecombineerd met microservice-architectuur en containerisatie van applicaties, lijken ze precies op de goede plek te komen.

6. Conclusie

In deze tutorial hebben we de concepten van twaalffactormethodologie doorgenomen. We hebben besproken hoe we een microservicearchitectuur kunnen gebruiken met Spring Boot om deze effectief te leveren. Verder hebben we elke factor in detail onderzocht en hoe we deze op onze applicatie kunnen toepassen. We hebben ook verschillende tools onderzocht om deze individuele factoren op een effectieve manier succesvol toe te passen.