Microservices Design Guide

Het is 2018, iedereen heeft gehoord over Microservices. Maar weet je hoe je er een moet ontwerpen?

Microservices is tegenwoordig een populair onderwerp onder software-ingenieurs. Laten we begrijpen hoe we echt modulaire, zakelijke agile IT-systemen kunnen bouwen met de architecturale stijl van Microservices.

Microservices Concept

Microservices-architectuur bestaat uit collecties van lichtgewicht, losjes gekoppelde services. Elke service implementeert een enkele zakelijke mogelijkheid. Idealiter zouden deze services voldoende samenhangend moeten zijn om onafhankelijk te ontwikkelen, testen, vrijgeven, implementeren, schalen, integreren en onderhouden.

Formele definitie
“De architecturale stijl van Microservice is een benadering voor het ontwikkelen van een enkele applicatie als een reeks kleine services, die elk hun eigen proces hebben en communiceren met lichtgewicht mechanismen, vaak een HTTP resource API. Deze services zijn gebouwd rond zakelijke mogelijkheden en onafhankelijk inzetbaar door volledig geautomatiseerde implementatiemachines. Er is een absoluut minimum aan gecentraliseerd beheer van deze services, die mogelijk in verschillende programmeertalen zijn geschreven en verschillende technologieën voor gegevensopslag gebruiken. "
- James Lewis en Martin Fowler

Karakteristieken van Microservices definiëren

  • Elke service is een lichtgewicht, onafhankelijke en losjes gekoppelde bedrijfseenheid.
  • Elke service heeft zijn eigen codebasis, beheerd en ontwikkeld door een klein team (meestal in een agile omgeving).
  • Elke service is verantwoordelijk voor een enkel deel van de functionaliteit (zakelijke mogelijkheden) en doet het goed.
  • Elke service kan de beste technologiestapel kiezen voor zijn gebruiksscenario's (het is niet nodig om in de hele applicatie in één framework te blijven).
  • Elke service heeft zijn eigen DevOp-plan (onafhankelijk testen, vrijgeven, implementeren, schalen, integreren en onderhouden).
  • Elke service wordt geïmplementeerd in een zelfstandige omgeving.
  • Diensten communiceren met elkaar door middel van goed gedefinieerde API's (slimme eindpunten) en eenvoudige protocollen zoals REST over HTTP (domme pijpen).
  • Elke service is verantwoordelijk voor het bewaren van zijn eigen gegevens en voor het behouden van de externe status (alleen als meerdere services dezelfde gegevens gebruiken, worden dergelijke situaties in een gemeenschappelijke gegevenslaag afgehandeld).

Voordelen van Microservices

Microservice is gemaakt om grote systemen op te schalen. Ze zijn ook geweldige mogelijkheden voor continue integratie en levering.

De schaalkubus: driedimensionaal model voor schaalbaarheid (Afbeelding: Nginx Blog)
  • Onafhankelijke schaling - Microservices-architectuur ondersteunt het Scale Cube-concept beschreven in het uitstekende boek The Art of Scalability. Bij het ontwikkelen van microservices om functionele ontleding te bereiken, schaalt de toepassing automatisch via de Y-as. Wanneer het verbruik hoog is, kunnen microservices via de X-as worden geschaald door te klonen met meer CPU en geheugen. Voor het distribueren van gegevens over meerdere machines kunnen grote databases worden gescheiden (sharding) in kleinere, snellere, eenvoudiger beheerde onderdelen die schaalverdeling op Z-as mogelijk maken.
  • Onafhankelijke releases en implementaties - Bugfixes en feature releases zijn beter beheersbaar en minder riskant, met microservices. U kunt een service bijwerken zonder de hele toepassing opnieuw te implementeren en een update ongedaan maken of terugdraaien als er iets misgaat.
  • Onafhankelijke ontwikkeling - Elke service heeft zijn eigen codebasis, die wordt ontwikkeld, getest en geïmplementeerd door een klein gericht team. Ontwikkelaars kunnen zich op slechts één service en een relatief kleine scope concentreren. Dit resulteert in verbeterde productiviteit, projectsnelheid, continue innovatie en kwaliteit bij de bron.
  • Sierlijke degradatie - Als een service uitvalt, wordt de impact ervan niet doorgegeven aan de rest van de applicatie en resulteert dit in een catastrofale uitval van het systeem, waardoor een zekere mate van anti-fragiliteit zich kan manifesteren.
  • Gedecentraliseerd bestuur - Ontwikkelaars zijn vrij om de technologiestapels te kiezen en ontwerpstandaarden en implementatiebeslissingen te nemen die het meest geschikt zijn voor hun service. Teams hoeven niet te worden bestraft vanwege technologische beslissingen uit het verleden.

Operationele zorgen

Onafhankelijke diensten alleen kunnen geen systeem vormen. Voor het echte succes van microservices-architectuur zijn aanzienlijke investeringen vereist om systeemoverschrijdende problemen aan te pakken, zoals:

  • Servicereplicatie - een mechanisme waarmee services eenvoudig kunnen worden geschaald op basis van metagegevens
  • Serviceregistratie en -detectie - een mechanisme om het zoeken van services mogelijk te maken en het eindpunt voor elke service te vinden
  • Servicebewaking en logboekregistratie - een mechanisme om logboeken van verschillende microservices te verzamelen en een consistente rapportage te bieden
  • Veerkracht - een mechanisme voor services om automatisch corrigerende maatregelen te nemen tijdens storingen
  • DevOps - een mechanisme voor het verwerken van continue integratie en implementatie (CI en CD)
  • API-gateway - een mechanisme voor het bieden van een toegangspunt voor klanten

Middleware & ontwerppatronen

API Gateway (één toegangspunt voor alle clients)

API Gateway Style Microservices Architecture (Afbeelding: Microsoft Azure Docs) - dit is het meest voorkomende ontwerppatroon dat wordt gebruikt in microservices. API Gateway is een intermediair met minimale routeringsmogelijkheden en fungeert gewoon als een 'domme pijp' zonder bedrijfslogica. Over het algemeen kunt u met API Gateway een beheerde API gebruiken via REST / HTTP. Andere soorten microservices-integratiepatronen: Point-to-point-stijl (services rechtstreeks vanuit client-app aanroepen) en Message Broker-stijl (asynchrone berichtenuitvoering).

API Gateway fungeert als een enkel toegangspunt voor alle clients en als een edge-service om microservices als beheerde API's aan de buitenwereld bloot te stellen. Het klinkt als een omgekeerde proxy, maar heeft ook extra verantwoordelijkheden zoals eenvoudige load-balancing, authenticatie en autorisatie, foutafhandeling, auditing, protocolvertalingen en routing. Het ontwikkelteam kan een van de volgende benaderingen selecteren om een ​​API-gateway te implementeren.

  • Bouw het programmatisch op - voor betere aanpassingen en controle
  • Implementeer een bestaand API-gatewayproduct - om initiële ontwikkeltijd te besparen en geavanceerde ingebouwde functies te gebruiken (Nadelen: dergelijke producten zijn afhankelijk van de leverancier en niet volledig gratis. Configuraties en onderhoud kunnen vaak vervelend en tijdrovend zijn)

Sommige ontwerppatronen die het gedrag van API Gateway verklaren zijn als volgt (lees Ontwerppatronen voor microservices).

  • Gateway-aggregatie - verzamel meerdere clientverzoeken (meestal HTTP-aanvragen) die meerdere interne microservices als één clientverzoek targeten, waardoor chattiness en latentie tussen consumenten en services wordt verminderd.
  • Gateway Offloading - stel individuele microservices in staat om hun shared service-functionaliteit naar het API-gatewayniveau te verplaatsen. Dergelijke horizontale functionaliteiten omvatten authenticatie, autorisatie, service discovery, fouttolerantiemechanismen, QoS, load balancing, logboekregistratie, analyse etc.
  • Gateway Routing (laag 7 routing, meestal HTTP-aanvragen) - routeverzoeken naar de eindpunten van interne microservices met behulp van een enkel eindpunt, zodat consumenten niet veel verschillende eindpunten hoeven te beheren

Merk op dat een API-gateway altijd een zeer beschikbaar en performant onderdeel moet zijn, omdat dit het toegangspunt tot het hele systeem is.

Event Bus (Pub / sub-bemiddelkanaal voor asynchrone gebeurtenisgestuurde communicatie)

Eventuele consistentie tussen microservices op basis van gebeurtenisgestuurde async-communicatie (Afbeelding: microsoft.com)

Om verschillende delen van de applicatie met elkaar te laten communiceren, ongeacht de volgorde van berichten (asynchroon) of welke taal ze gebruiken (taal-agnostisch), kan de evenementbus worden gebruikt. De meeste evenementbussen ondersteunen publiceren / abonneren, distribueren, point to point en request-response-berichten. Sommige evenementbussen (zoals in Vert.x) zorgen ervoor dat clientzijde kan communiceren met overeenkomstige serverknooppunten met behulp van dezelfde evenementbus, wat een coole functie is die geliefd is bij full-stack teams.

Service Mesh (zijspan voor interservice communicatie)

Interservice-communicatie met behulp van Service Mesh-stijl (Afbeelding: Microservices in Practice)Hoe servicegaas wordt gebruikt in een applicatie (Afbeelding: christianposta.com)

Service Mesh implementeert Sidecar-patroon door helperinfrastructuur te bieden voor interservice-communicatie. Het bevat functies zoals veerkracht (fouttolerantie, load balancing), service discovery, routing, observability, beveiliging, toegangscontrole, communicatieprotocolondersteuning etc.

Hoe Service Meshes in de netwerkstack passen (Afbeelding: christianposta.com)

In de praktijk wordt een Sidecar-instantie naast elke service geïmplementeerd (idealiter in dezelfde container). Ze kunnen communiceren via primitieve netwerkfuncties van de service. Het Control Plane of Service Mesh wordt afzonderlijk geïmplementeerd om centrale mogelijkheden te bieden, zoals service discovery, toegangscontrole en waarneembaarheid (monitoring, gedistribueerde logging). Het belangrijkste is dat Service Mesh-stijl ontwikkelaars in staat stelt om netwerkcommunicatiefuncties los te koppelen van microservicecode en services alleen gericht te houden op de zakelijke mogelijkheden. (Lees: Netflix Prana, Service Mesh voor microservices)

Hoewel bovenstaande afbeeldingen directe verbindingen tussen services aangeven, zou de leuke manier om de interservice-communicatie af te handelen een eenvoudige Event Bus als bemiddelaar gebruiken om de koppeling op een minimaal niveau te houden.

Backends voor Frontends (BFF)

Backends implementeren voor Frontends en Aggregator-patronen op API Gateway-niveau (Afbeelding: microsoft.com)

Als de applicatie elke API moet afstemmen op het type app van de client (web, mobiel, verschillende platforms), kunnen verschillende regels (configs) worden afgedwongen via een gevel of kunnen afzonderlijke builds worden gebruikt op basis van clientmogelijkheden. Dit kan worden geïmplementeerd op API Gateway-niveau zelf of parallel aan het serviceniveau. Dit patroon is handig om specifieke gebruikerservaringen te bieden. Het ontwikkelteam moet echter voorzichtig genoeg zijn om BFF's tot een beheersbare limiet te houden.

Best practices

Domain Driven Design - Modeldiensten rond het bedrijfsdomein.

Om grote modellen en teams aan te kunnen, kan Domain Driven Design (DDD) worden toegepast. Het gaat over grote modellen door ze in verschillende begrensde contexten te verdelen en expliciet te zijn over hun onderlinge relaties en onderliggend domein. Deze begrensde contexten kunnen worden omgezet in afzonderlijke microservices op het niveau van de applicatie-ontwerp (Lees: Bounded Context in Domain-Driven Design).

Gedecentraliseerd gegevensbeheer (vermijd gedeelde databases). Wanneer meerdere services een gedeeld gegevensschema gebruiken, kan dit een nauwe koppeling op de gegevenslaag tot stand brengen. Om dit te voorkomen, moet elke service zijn eigen logica voor gegevenstoegang en een afzonderlijke gegevensopslag hebben. Het ontwikkelteam is vrij om de methode voor gegevenspersistentie te kiezen die het beste past bij elke service en aard van de gegevens.

Vermijd gedeelde datastores en datatoegangsmechanismen (Afbeelding: christianposta.com)

Slimme eindpunten en domme pijpen - Elke service bezit een goed gedefinieerde API voor externe communicatie. Voorkom lekkende implementatiedetails. Gebruik voor communicatie altijd eenvoudige protocollen zoals REST via HTTP.

Asynchrone communicatie - Wanneer asynchrone communicatie tussen services wordt gebruikt, wordt de gegevensstroom niet geblokkeerd voor andere services.

Synchrone versus asynchrone berichten (Afbeelding: microsoft.com)

Vermijd koppeling tussen services - Services moeten losse koppeling en een hoge functionele samenhang hebben. De belangrijkste oorzaken van koppeling zijn gedeelde database-schema's en rigide communicatieprotocollen.

Decentraliseer ontwikkeling - Vermijd het delen van codebases, gegevensschema's of leden van het ontwikkelteam tussen meerdere services / projecten. Laat ontwikkelaars zich richten op innovatie en kwaliteit bij de bron.

Domain Houd domeinkennis buiten de gateway. Laat de gateway routing- en transversale problemen afhandelen (authenticatie, SSL-beëindiging).

Op tokens gebaseerde authenticatie - in plaats van het implementeren van beveiligingscomponenten op elk microservices-niveau dat in gesprek is met een gecentraliseerde / gedeelde gebruikersrepository en de authenticatie-informatie ophaalt, kunt u overwegen om authenticatie op API Gateway-niveau te implementeren met veelgebruikte API-beveiligingsstandaarden zoals OAuth2 en OpenID Aansluiten. Na het verkrijgen van een auth-token van de auth-provider, kan het worden gebruikt om te communiceren met andere microservices.

Microservicebeveiliging met OAuth2 en OpenID Connect (afbeelding: Kasun's blog)

Gebeurtenis-aangedreven karakter - Mensen zijn autonome agenten die op gebeurtenissen kunnen reageren. Kunnen onze systemen niet zo zijn? (Lees: Waarom microservices door een gebeurtenis moeten worden gestuurd: Autonomie versus autoriteit)

Eventuele consistentie - Vanwege de hoge samenhang in microservices is het moeilijk om een ​​sterke consistentie in het hele systeem te bereiken. Het ontwikkelingsteam zal de uiteindelijke consistentie moeten afhandelen.

Fouttolerantie - Omdat het systeem uit meerdere services en middleware-componenten bestaat, kunnen storingen heel gemakkelijk ergens optreden. Het implementeren van patronen zoals circuitbreuk, schot, nieuwe pogingen, time-outs, fail fast, failover caching, snelheidsbegrenzers, load shedders in dergelijke kwetsbare componenten kunnen de risico's van grote storingen minimaliseren. (Lees: een Microservices-architectuur ontwerpen voor fouten)

Product engineering - Microservices zullen goed werken zolang het is ontworpen als een product, niet als een project. Het gaat er niet om het op de een of andere manier te laten werken en vóór de deadlines te leveren, maar om een ​​commitment op lange termijn van uitmuntende engineering.

Microservices in de praktijk

Wanneer Microservices te gebruiken

Microservices-architectuur past het beste bij:

  • Toepassingen met hoge schaalbaarheidsbehoeften
  • Projecten met hoge lossnelheid
  • Businesscases met rijke domeinen of veel subdomeinen
  • Agile omgevingen met kleine, cross-functionele ontwikkelingsteams die samen grote producten ontwikkelen (lees: het echte succesverhaal van Microservices Architectures)

Enkele go-to-frameworks voor het implementeren van microservices

  • Vert.x - lichtgewicht, eenvoudig te begrijpen / implementeren / onderhouden, polyglot (ondersteunt vele talen), event-driven, niet-blokkering, tot nu toe de beste prestaties en schaalbaarheid bij het omgaan met hoge concurrency-behoeften met minimale hardware, niet-geïnioneerd ( biedt alleen bruikbare bakstenen, ontwikkelaars hebben de vrijheid om innovatief te zijn en hun applicaties zorgvuldig te bouwen, niet zoals traditionele beperkende kaders)
  • Akka - bevredigende prestaties, implementeert actormodel, goed voor reactieve en gebeurtenisgestuurde microservices
  • SpringBoot / Cloud - eenvoudig te starten (vertrouwde paradigma's), gebaseerd op het goede oude Spring-framework, een beetje zwaar framework, veel integraties beschikbaar, grote community-ondersteuning
  • Dropwizard - goed voor de snelle ontwikkeling van RESTful-webservices, wordt volledig geladen met een aantal leuke Java-tools en bibliotheken zoals Google Guava, Jetty-server, Logback, Hibernate Validator, Joda Time, Jersey en Jackson.

Implementatie opties

  • Containers - goed voor het afdwingen van DevOp-doelstellingen (snelle ontwikkeling, kortere time-to-market, naadloze schaling)
  • Cloud - goed voor het bouwen van betrouwbare en schaalbare infrastructuur om geografisch verspreide gebruikers te bedienen
  • Serverloos - goed voor het verwerken van zeer volatiel verkeer
  • Handhaaf een eigen IT-infrastructuur - goed voor degenen die over hoge capaciteiten en middelen beschikken om de volledige infrastructuur te bouwen

Concepten ontwikkelen rond microservices

  • Zelfstandige systemen - stel software samen van onafhankelijke systemen (zoals verticals in microservices)
  • Micro Frontends - deel monolith web-UI's op in onafhankelijke functies die kunnen worden ontwikkeld als zelfstandige UI-componenten en waarmee direct kan worden gecommuniceerd met microservices

Zoekwoorden voor Google (en studeren!)

Domain Driven Design (DDD) | Bounded Context (BC) | Polyglot-persistentie (PP) | Command and Query Responsibility Segregation (CQRS) | Command Query Separation (CQS) | Evenement-sourcing (ES) | CAP-stelling | Eventuele consistentie | Twaalffactor-app | SOLID Principes |

Architectuursuggesties

Microservices-architectuur voor een online shopping-applicatie (Afbeelding: microsoft.com) - Deze architectuur wordt voorgesteld door Microsoft-ontwikkelaars die Microsoft-technologieën gebruiken. Hier is de API Gateway aangepast om web- en mobiele gebruikers anders te behandelen. Voor datalagen worden datastore-technologieën zorgvuldig geselecteerd op basis van de zakelijke mogelijkheden (relationele databases voor gestructureerde data, Redis voor tijdelijke datacaching, MongoDB en CosmosDB voor ongestructureerde data). Interservice-communicatie afgehandeld door de evenementenbus. Afgezien van technologieën is dit het meest voorkomende integratiepatroon dat wordt gebruikt in op microservices gebaseerde toepassingen.Microservices-architectuur voor een applicatie die realtime updates weergeeft aan eindgebruikers die grote hoeveelheden inputdatastromen gebruiken die afkomstig zijn van verschillende gebeurtenisbronnen (bijv. Verkeersgegevens, weergegevens, beursfeeds, posts op sociale media, sensoruitgangen). Deze invoergegevensstromen worden aanvankelijk verzameld door een gebeurtenislogboek geïmplementeerd met behulp van Kafka. Het bevat gegevens op schijf en kan dus worden gebruikt voor batchverbruiksdoeleinden (analyse, rapportage, gegevenswetenschap, back-up, auditing) of worden verzonden voor realtime consumptiedoeleinden (operationele analyse, CEP, admin-dashboards, waarschuwings-apps). Volgens dit diagram wordt de continue binnenkomende stroom echter met gespecificeerde intervallen met behulp van Spark in microbatches verdeeld en in de WSO2 Siddhi CEP-motor ingevoerd. Vervolgens identificeert het de gebeurtenissen en houdt deze in ongestructureerde vormen aan met behulp van MongoDB-gegevensopslag. Microservices verbruiken deze gegevens en geven deze weer aan de eindgebruikers. Als je goed naar het ontwerp kijkt, aangezien Vert.x-eventbus de mogelijkheid heeft om verbindingen met frontend UI-componenten te maken, is die functie gebruikt om alleen de relevante onderdelen in de UI efficiënt bij te werken. Afgezien van technologieën is dit een geweldige architectuur voor op evenementen gebaseerde, niet-blokkerende, op microservices gebaseerde applicaties.Cloud native omni-channel microservices-architectuur voor een orderbeheertoepassing (Afbeelding: ibm.com) - Een belangrijke specialiteit in dit ontwerp is dat IBM architecten in plaats van een API-gateway een randlaag hebben voorgesteld met afzonderlijke backends voor elk clientside kanaal ( mobiele apps, web-apps, IOT-apparaten, API-consumenten). Een andere specialiteit is dat de microservices-laag is verdeeld in 2 sublagen genaamd Business Logic-laag en Foundational-laag. Foundational Layer (ook bekend als Core Services Layer) houdt zich bezig met persistentie en integratietaken met behulp van verschillende native cloudservices (clouddatastores, Elasticsearch-engines die een Watson-gesprek integreren en indexeren). Business Logic-laag integreert gegevens uit de basislaag en levert zinvolle zakelijke mogelijkheden. Dit zou een geweldige architectuur zijn voor het bedienen van een zeer groot aantal gebruikers die geografisch verspreid zijn en toegang hebben tot applicaties via verschillende platforms.
Geniet je er tot nu toe van? Vergeet niet aan te bevelen