Patroon: Microservice-architectuur
Context
U ontwikkelt een server-side enterprise-applicatie die een groot aantal verschillende clients moet ondersteunen, waaronder desktopbrowsers, mobiele browsers en native mobiele applicaties. De applicatie kan ook een API beschikbaar stellen die door derden kan worden gebruikt. Het kan ook worden geïntegreerd met andere applicaties via webservices of een message broker. De applicatie behandelt verzoeken (HTTP-verzoeken en berichten) door bedrijfslogica uit te voeren; toegang krijgen tot een database; berichten uitwisselen met andere systemen; en het retourneren van een HTML / JSON / XML-antwoord. Er zijn logische componenten die overeenkomen met verschillende functionele gebieden van de applicatie.
Probleem
Wat is de implementatie-architectuur van de applicatie?
Krachten
- Er werkt een team van ontwikkelaars aan de applicatie
- Nieuwe teamleden moeten snel productief worden
- De applicatie moet gemakkelijk te begrijpen zijn en wijzigen
- U wilt continue implementatie van de applicatie oefenen
- U moet meerdere instanties van de applicatie op meerdere machines draaien om te voldoen aan de vereisten voor schaalbaarheid en beschikbaarheid
- U wilt profiteren van opkomende technologieën (frameworks, programmeertalen, enz.)
Oplossing
Definieer een architectuur die de applicatie structureert als een reeks losjes gekoppelde, samenwerkende services. Deze benadering komt overeen met de Y-as van de Scale Cube. Elke service is:
- Zeer onderhoudbaar en testbaar – maakt ra pid en frequente ontwikkeling en implementatie
- Losjes gekoppeld aan andere services – stelt een team in staat om het grootste deel van de tijd zelfstandig aan hun service (s) te werken zonder te worden beïnvloed door wijzigingen in andere services en zonder andere services te beïnvloeden
- Onafhankelijk inzetbaar – stelt een team in staat om hun service in te zetten zonder te hoeven coördineren met andere teams.
- Geschikt om te worden ontwikkeld door een klein team – essentieel voor hoge productiviteit door het hoge communicatieve hoofd van grote teams
Services communiceren via synchrone protocollen zoals HTTP / REST of asynchrone protocollen zoals AMQP. Services kunnen onafhankelijk van elkaar worden ontwikkeld en geïmplementeerd. elke service heeft zijn eigen database om worden losgekoppeld van andere services. Gegevensconsistentie tussen services wordt gehandhaafd met behulp van het Saga-patroon.
Lees dit artikel voor meer informatie over de aard van een service.
Voorbeelden
Fictieve e-commercetoepassingen op
Stel dat u een e-commerce-applicatie bouwt die bestellingen van klanten opneemt, de voorraad en het beschikbare krediet verifieert en verzendt. De applicatie bestaat uit verschillende componenten, waaronder de StoreFrontUI, die de gebruikersinterface implementeert , samen met enkele backend-services voor het controleren van krediet, het bijhouden van voorraad en verzendopdrachten. De applicatie bestaat uit een reeks services.
Laat me de code zien
Zie de voorbeeldapplicaties die zijn ontwikkeld door Chris Richardson. Deze voorbeelden op Github illustreren verschillende aspecten van de microservice-architectuur.
Resulterende context
Voordelen
Deze oplossing heeft een aantal voordelen:
- Maakt continue levering en implementatie van grote, complexe applicaties mogelijk.
- Verbeterde onderhoudbaarheid – elke service is relatief klein en dus gemakkelijker te begrijpen en te wijzigen
- Betere testbaarheid – services zijn kleiner en sneller te testen
- Betere inzetbaarheid – services kan onafhankelijk worden ingezet
- Het stelt u in staat de ontwikkelingsinspanningen rond meerdere, autonome teams te organiseren. Elk (zogenaamde twee pizza) team bezit en is verantwoordelijk voor één of meerdere diensten. Elk team kan zijn services onafhankelijk van alle andere teams ontwikkelen, testen, implementeren en schalen.
- Elke microservice is relatief klein:
- Gemakkelijker voor een ontwikkelaar om te begrijpen
- De IDE maakt ontwikkelaars sneller productiever
- De applicatie start sneller, waardoor ontwikkelaars productiever worden en implementaties worden versneld
- Verbeterde foutisolatie. Als er bijvoorbeeld een geheugenlek is in de ene service, wordt alleen die service beïnvloed. De andere services zullen verzoeken blijven behandelen. Ter vergelijking: een zich misdragend onderdeel van een monolithische architectuur kan het hele systeem platleggen.
- Elimineert elke langetermijnverplichting voor een technologiestack. Bij het ontwikkelen van een nieuwe service kunt u een nieuwe technologiestack kiezen. Evenzo kunt u bij het maken van grote wijzigingen aan een bestaande service deze herschrijven met een nieuwe technologiestack.
Nadelen
Deze oplossing heeft een aantal nadelen:
- Ontwikkelaars moeten omgaan met de extra complexiteit van het creëren van een gedistribueerd systeem:
- Ontwikkelaars moeten het communicatiemechanisme tussen services implementeren en gedeeltelijke storingen aanpakken.
- Het implementeren van verzoeken die meerdere services omvatten is moeilijker
- Het testen van de interacties tussen services is meer moeilijk
- Het implementeren van verzoeken die meerdere services omvatten, vereist een zorgvuldige coördinatie tussen de teams.
- Ontwikkelaarstools / IDE’s zijn gericht op het bouwen van monolithische applicaties en bieden geen expliciete ondersteuning voor het ontwikkelen van gedistribueerde applicaties.
- Complexiteit van implementatie. In productie is er ook de operationele complexiteit van het implementeren en beheren van een systeem dat uit veel verschillende services bestaat.
- Verhoogd geheugengebruik. De microservice-architectuur vervangt N monolithische applicatie-instances door NxM-services-instances. Als elke service in zijn eigen JVM (of equivalent) wordt uitgevoerd, wat meestal nodig is om de instanties te isoleren, is er de overhead van M keer zoveel JVM-runtimes. Bovendien, als elke service op zijn eigen VM draait (bijvoorbeeld EC2-instantie), zoals het geval is bij Netflix, is de overhead zelfs nog hoger.
Problemen
Er zijn veel problemen die u moet aanpakken.
Wanneer moet u de microservice-architectuur gebruiken?
Een uitdaging bij het gebruik van deze aanpak is beslissen wanneer het zinvol is om deze te gebruiken. Bij het ontwikkelen van de eerste versie van een applicatie heb je vaak niet de problemen die deze aanpak oplost. bovendien zal het gebruik van een uitgebreide, gedistribueerde architectuur de ontwikkeling vertragen. dit kan een groot probleem zijn voor startups wiens grootste uitdaging vaak is om het businessmodel en de bijbehorende Het gebruik van Y-as-splitsingen kan het veel moeilijker maken om snel te itereren. later, echter, wanneer de uitdaging is hoe te schalen en u functionele decompositie moet gebruiken, kunnen de verwarde afhankelijkheden het moeilijk maken om uw monolithische applicatie op te splitsen in een set services.
Hoe de applicatie te ontleden integratie in services?
Een andere uitdaging is beslissen hoe het systeem in microservices moet worden onderverdeeld. Dit is een hele kunst, maar er zijn een aantal strategieën die kunnen helpen:
- Ontleed op basis van zakelijke mogelijkheden en definieer services die overeenkomen met zakelijke mogelijkheden.
- Ontleed op basis van domeingestuurd ontwerpsubdomein.
- Ontleed op basis van werkwoord of use case en definieer services die verantwoordelijk zijn voor bepaalde acties . bijv. een
Shipping Service
die verantwoordelijk is voor het verzenden van volledige bestellingen. - Ontbind op basis van zelfstandige naamwoorden of bronnen door een service te definiëren die verantwoordelijk is voor alle bewerkingen op entiteiten / bronnen van een bepaalde type. bijv. een
Account Service
die verantwoordelijk is voor het beheren van gebruikersaccounts.
Idealiter zou elke service slechts een klein aantal verantwoordelijkheden moeten hebben. (oom) Bob Martin spreekt over het ontwerpen van klassen met behulp van het Single Responsibility Principle (SRP). de SRP definieert een verantwoordelijkheid van een klasse als een reden om te veranderen, en stelt dat een klasse maar één reden mag hebben om te veranderen. het is logisch om de SRP toe te passen op service design ook.
Een andere analogie die helpt bij service-ontwerp is het ontwerp van Unix-hulpprogramma’s. Unix biedt een groot aantal hulpprogramma’s zoals grep, cat en find. Elk hulpprogramma doet precies één ding, vaak uitzonderlijk goed, en is bedoeld om te worden gecombineerd met andere hulpprogramma’s met behulp van een shellscript om complexe taken uit te voeren.
Hoe de gegevensconsistentie te behouden?
Om een losse koppeling te garanderen, heeft elke service zijn eigen Het handhaven van gegevensconsistentie tussen services is een uitdaging, omdat 2-fase-commit / gedistribueerde transacties dat niet zijn een optie voor veel toepassingen. een toepassing moet in plaats daarvan het Saga-patroon gebruiken. een service publiceert een gebeurtenis wanneer de gegevens veranderen. andere diensten gebruiken die gebeurtenis en werken hun gegevens bij. er zijn verschillende manieren om gegevens op betrouwbare wijze bij te werken en gebeurtenissen te publiceren, waaronder event sourcing en Transaction Log Tailing.
Hoe queries te implementeren?
Een andere uitdaging is het implementeren van queries die gegevens moeten ophalen die eigendom zijn van meerdere services.
- De API Samenstelling en Command Query Responsibility Segregation (CQRS) patronen.
Er zijn veel patronen gerelateerd aan het microservicepatroon. De monolithische architectuur is een alternatief voor de microservice-architectuur. De andere patronen pakken problemen aan die u tegenkomt bij het toepassen van de microservice-architectuur.
- Decompositiepatronen
- Decompositie op basis van zakelijke mogelijkheden
- Decompositie op subdomein
- Het Database per Service-patroon beschrijft hoe elk service heeft een eigen database om losse koppeling te garanderen.
- Het API Gateway-patroon definieert hoe clients toegang krijgen tot de services in een microservice-architectuur.
- De patronen Client-side Discovery en Server-Side Discovery worden gebruikt om verzoeken voor een client naar een beschikbare service-instantie in een microservice-architectuur.
- De patronen voor Berichten en externe procedure aanroep zijn twee verschillende manieren waarop services kunnen communiceren.
- De patronen Enkele service per host en Meerdere services per host zijn twee verschillende implementatiestrategieën.
- Transversale betreft patronen: Microservice-chassispatroon en externe configuratie
- Testpatronen: servicecomponenttest en service-integratiecontracttest
- Circuit Breaker
- Toegangstoken
- Observeerbaarheidspatronen:
- Log-aggregatie
- Applicatiestatistieken
- Auditregistratie
- Gedistribueerde tracering
- Tracking van uitzonderingen
- API voor gezondheidscontrole
- Implementaties en wijzigingen registreren
- UI-patronen:
- Samenstelling van paginafragmenten aan serverzijde
- Samenstelling van gebruikersinterface aan clientzijde
Bekende toepassingen
De meeste grootschalige websites, waaronder Netflix, Amazon en eBay, zijn geëvolueerd van een monolithische architectuur naar een microservice-architectuur.
Netflix, een zeer populaire videostreamingservice die verantwoordelijk is voor maximaal 30% van het internetverkeer, heeft een grootschalige, servicegerichte architectuur. ze verwerken meer dan een miljard oproepen per dag naar hun videostreaming-API vanaf meer dan 800 verschillende soorten apparaten. elke API roept gemiddeld zes fans op aanroepen naar backend-services.
Amazon.com had oorspronkelijk een architectuur met twee niveaus. om op te schalen migreerden ze naar een servicegeoriënteerde architectuur die uit honderden backend-services bestond. Verschillende applicaties noemen deze services, inclusief de applicaties die de Amazon.com-website en de webservice-API implementeren. De Amazon.com-websitetoepassing roept 100-150 services aan om het gegevens die werden gebruikt om een webpagina te bouwen.
De veilingsite ebay.com evolueerde ook van een monolithische architectuur naar een servicegeoriënteerde architectuur. de applicatielaag bestaat uit meerdere onafhankelijke applicaties. elke applicatie implementeert de bedrijfslogica voor een specifiek functiegebied, zoals kopen of verkopen. Elke applicatie gebruikt X-as splitsingen en sommige applicaties zoals zoeken gebruiken Z-as splitsingen. eBay.com past ook een combinatie van X-, Y- en Z-stijl schalen toe op de databaselaag.
Er zijn talloze andere voorbeelden van bedrijven die de microservice-architectuur gebruiken.
Chris Richardson heeft voorbeelden van op microservices gebaseerde applicaties.
Zie ook
Zie mijn keynote van Code Freeze 2018, die een goede introductie biedt tot de microservice-architectuur.