Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Microservices zijn een populaire architectuurstijl voor het bouwen van robuuste, zeer schaalbare en onafhankelijk implementeerbare toepassingen die snel met veranderende vereisten kunnen meegroeien. Het bouwen van een succesvolle microservicesarchitectuur vereist een fundamentele verschuiving in mindset. Het gaat verder dan het opsplitsen van een toepassing in kleinere services. U moet ook opnieuw nadenken over hoe systemen worden ontworpen, geïmplementeerd en beheerd.
Een microservicearchitectuur bestaat uit een verzameling kleine, autonome services. Elke service is zelfstandig en moet één bedrijfsmogelijkheid binnen een gebonden context implementeren. Een gebonden context is een natuurlijke divisie binnen een bedrijf en biedt een expliciete grens waarbinnen een domeinmodel bestaat.
Wat zijn microservices?
Microservices zijn kleine, onafhankelijke en losjes gekoppelde onderdelen die één klein team van ontwikkelaars kan schrijven en onderhouden. Elke service wordt beheerd als een afzonderlijke codebasis, waardoor een klein team deze efficiënt kan verwerken. Omdat services onafhankelijk kunnen worden geïmplementeerd, kunnen teams bestaande services bijwerken zonder de hele toepassing opnieuw te bouwen of opnieuw te implementeren. In tegenstelling tot traditionele modellen met een gecentraliseerde gegevenslaag, zijn microservices verantwoordelijk voor het behouden van hun eigen gegevens of externe status. Ze communiceren via goed gedefinieerde API's, waardoor interne implementaties verborgen blijven voor andere services. Deze architectuur biedt ook ondersteuning voor polyglotprogrammering, wat betekent dat services niet dezelfde technologiestack, bibliotheken of frameworks hoeven te delen.
Onderdeel
Naast de services zelf worden andere onderdelen weergegeven in een typische microservicesarchitectuur:
Beheer of indeling: Dit beheeronderdeel verwerkt microservicesindeling. Het plant en implementeert services op verschillende knooppunten, detecteert fouten, herstelt van fouten en stelt autoscaling in op basis van vraag. Een containerindelingsplatform zoals Kubernetes biedt deze functionaliteit doorgaans. In cloudeigen omgevingen bieden oplossingen zoals Azure Container Apps beheerde indeling en ingebouwde schaalaanpassing. Deze hulpprogramma's verminderen de complexiteit van de implementatie en operationele overhead.
API-gateway: De API-gateway fungeert als het toegangspunt voor clients. Clients verzenden aanvragen naar de API-gateway in plaats van services rechtstreeks aan te roepen. De gateway stuurt deze aanvragen door naar de juiste back-endservices. Het verwerkt ook kruislingse problemen, zoals verificatie, logboekregistratie en taakverdeling. In cloudeigen microservicesarchitecturen ondersteunen lichtgewicht serviceproxy's zoals Envoy en Nginx interne service-naar-service-communicatie. Dit type intern verkeer, ook wel oost-westverkeer genoemd, maakt geavanceerde routering en verkeersbeheer mogelijk.
Berichtgerichte middleware: Berichtenplatforms zoals Apache Kafka en Azure Service Bus maken asynchrone communicatie in microservices mogelijk door losse koppeling en ondersteuning te bieden voor hoge schaalbaarheid. Ze vormen de basis van gebeurtenisgestuurde architecturen. Met deze aanpak kunnen services in realtime reageren op gebeurtenissen en communiceren via asynchrone berichten.
Observability: Een effectieve waarneembaarheidsstrategie helpt teams de betrouwbaarheid van het systeem te behouden en problemen snel op te lossen. Gecentraliseerde logboekregistratie brengt logboeken samen ter ondersteuning van eenvoudigere diagnostische gegevens. Realtime bewaking met agents en frameworks voor het bewaken van toepassingsprestaties, zoals OpenTelemetry, biedt inzicht in de systeemstatus en prestaties. Met gedistribueerde tracering worden aanvragen over servicegrenzen bijgehouden. Het helpt teams knelpunten te vinden en de prestaties te verbeteren.
Gegevensbeheer: Een goed ontworpen databasearchitectuur ondersteunt autonomie en schaalbaarheid. Microservices gebruiken vaak polyglot persistence door verschillende databasetypen, zoals SQL of NoSQL, te kiezen op basis van de specifieke behoeften van elke service. Deze benadering is afgestemd op domeingestuurd ontwerp (DDD) en het idee van gebonden context. Elke service is eigenaar van de gegevens en het schema. Dit eigendom vermindert afhankelijkheden tussen services en maakt het mogelijk om services onafhankelijk van elkaar te ontwikkelen. Dit gedecentraliseerde model verbetert de flexibiliteit, prestaties en systeemtolerantie.
Voordelen
Wendbaarheid: Omdat microservices onafhankelijk van elkaar worden geïmplementeerd, is het eenvoudiger om bugfixes en functiereleases te beheren. U kunt een service bijwerken zonder de hele toepassing opnieuw te implementeren en een update terug te draaien als er iets misgaat. Als u in veel traditionele toepassingen een bug in één deel van de toepassing vindt, kan het hele releaseproces worden geblokkeerd. Een fout kan bijvoorbeeld nieuwe functies blokkeren als u een foutoplossing moet integreren, testen en publiceren.
Kleine, gerichte teams: Een microservice moet klein genoeg zijn dat één functieteam deze kan bouwen, testen en implementeren. Inzet van kleinere teams stimuleert meer flexibiliteit. Grote teams zijn meestal minder productief omdat de communicatie langzamer is, de overhead van het beheer toeneemt en de flexibiliteit afneemt.
Kleine codebasis: In een monolithische toepassing raken codeafhankelijkheden vaak in de loop van de tijd in de war. Het toevoegen van een nieuwe functie vereist mogelijk wijzigingen in veel onderdelen van de codebasis. Een microservicesarchitectuur voorkomt dit probleem door geen code of gegevensarchieven te delen. Deze aanpak minimaliseert afhankelijkheden en maakt het eenvoudiger om nieuwe functies te introduceren.
Mix van technologieën: Teams kunnen de technologie kiezen die het beste bij hun service past door een combinatie van technologiestacks te gebruiken.
Foutisolatie: Als een afzonderlijke microservice niet meer beschikbaar is, verstoort deze de hele toepassing niet zolang er upstream-microservices zijn ontworpen om fouten correct te verwerken. U kunt bijvoorbeeld het circuitonderbrekerpatroon implementeren of u kunt uw oplossing zo ontwerpen dat de microservices met elkaar communiceren met behulp van asynchrone berichtpatronen.
Schaalbaarheid: Services kunnen onafhankelijk worden geschaald. Met deze methode kunt u subsystemen uitschalen waarvoor meer resources nodig zijn zonder de hele toepassing uit te schalen. Gebruik een orchestrator zoals Kubernetes om een hogere dichtheid van services toe te voegen aan één host, wat efficiënter resourcegebruik mogelijk maakt.
Gegevensisolatie: Het bijwerken van een schema is eenvoudiger in een microservicearchitectuur omdat er slechts één microservice wordt beïnvloed. Monolithische toepassingen kunnen daarentegen schemawijzigingen bemoeilijken, omdat meerdere onderdelen vaak met dezelfde gegevens werken. Deze gedeelde toegang maakt eventuele wijzigingen mogelijk riskant.
Uitdagingen
De voordelen van microservices worden geleverd met compromissen. Houd rekening met de volgende uitdagingen voordat u een microservicearchitectuur maakt:
Complexiteit: Een microservicestoepassing heeft meer bewegende onderdelen dan de equivalente monolithische toepassing. Elke service is eenvoudiger, maar het hele systeem als geheel is complexer. Houd rekening met uitdagingen zoals servicedetectie, gegevensconsistentie, transactiebeheer en communicatie tussen services wanneer u uw toepassing ontwerpt.
Ontwikkeling en testen: Het schrijven van een kleine service die afhankelijk is van andere afhankelijke services vereist een andere benadering dan het schrijven van een traditionele monolithische of gelaagde toepassing. Bestaande hulpprogramma's zijn niet altijd ontworpen om te werken met serviceafhankelijkheden. Herstructureren tussen servicegrenzen kan lastig zijn. Het is ook lastig om serviceafhankelijkheden te testen, met name wanneer de toepassing zich snel ontwikkelt.
Gebrek aan governance: De gedecentraliseerde benadering van het bouwen van microservices heeft voordelen, maar kan ook leiden tot problemen. Mogelijk hebt u zoveel verschillende talen en frameworks die de toepassing moeilijk te onderhouden heeft. Het kan handig zijn om een aantal projectbrede standaarden in te stellen, zonder de flexibiliteit van teams te beperken. Deze methode is met name van toepassing op kruislingse functionaliteit, zoals logboekregistratie.
Netwerkcongestie en latentie: Het gebruik van veel kleine, gedetailleerde services kan leiden tot meer communicatie tussen services. Als de keten van serviceafhankelijkheden te lang wordt (service A roept B aan, die C... aanroept), kan de extra latentie een probleem worden. U moet API's zorgvuldig ontwerpen. Vermijd te veel chatachtige API's, denk na over serialisatie-indelingen en zoek naar plaatsen om asynchrone communicatiepatronen te gebruiken, zoals het patroonQueue-Based Load Leveling.
Gegevensintegriteit: Elke microservice is verantwoordelijk voor zijn eigen persistentie van gegevens. Als gevolg hiervan kan gegevensconsistentie tussen meerdere services een uitdaging zijn. Verschillende services behouden gegevens op verschillende momenten, met behulp van verschillende technologie en met mogelijk verschillende niveaus van succes. Wanneer meer dan één microservice betrokken is bij het persistent maken van nieuwe of gewijzigde gegevens, is het onwaarschijnlijk dat de volledige gegevenswijziging kan worden beschouwd als een atomische, consistente, geïsoleerde en duurzame (ACID)-transactie. In plaats daarvan is de techniek meer afgestemd op Basically Available, Soft State, Eventual Consistency (BASE). Omhels waar mogelijk uiteindelijke consistentie.
Beheer: Een succesvolle microservicearchitectuur vereist een volwassen DevOps-cultuur. Gecorreleerde logregistratie tussen diensten kan lastig zijn. Logboekregistratie moet doorgaans meerdere serviceaanroepen correleren voor één gebruikersbewerking.
Versiebeheer: Updates voor een service mogen services die ervan afhankelijk zijn, niet verbreken. Het is mogelijk dat op een bepaald moment meerdere services tegelijk worden bijgewerkt, dus zonder een zorgvuldig ontwerp kunnen er al snel problemen ontstaan met achterwaartse of voorwaartse compatibiliteit.
Vaardigheden: Microservices zijn zeer gedistribueerde systemen. Evalueer zorgvuldig of het team de vaardigheden en ervaring heeft om succesvol te zijn.
Beste praktijken
Modelservices rond het bedrijfsdomein. Gebruik DDD om gebonden contexten te identificeren en duidelijke servicegrenzen te definiëren. Vermijd het maken van te gedetailleerde services, waardoor de complexiteit kan toenemen en de prestaties kunnen worden verminderd.
Alles decentraliseren. Afzonderlijke teams zijn verantwoordelijk voor het ontwerpen en bouwen van services end-to-end. Vermijd het delen van code of gegevensschema's.
Standaardiseer uw technologische keuzes door het aantal talen en frameworks te beperken dat u gebruikt. Stel platformbrede standaarden in voor logboekregistratie, bewaking en implementatie.
Gegevensopslag moet privé zijn voor de service die eigenaar is van de gegevens. Gebruik de beste opslag voor elke service en elk gegevenstype.
Services communiceren via goed ontworpen API's. Vermijd het lekken van implementatiedetails. API's moeten het domein modelleren, niet de interne implementatie van de service.
Vermijd koppeling tussen services. Oorzaken van koppeling zijn gedeelde databaseschema's en starre communicatieprotocollen.
Verbeter de beveiliging met behulp van wederzijdse Transport Layer Security (mTLS) voor service-naar-service-versleuteling. Implementeer op rollen gebaseerd toegangsbeheer en gebruik API-gateways om beleid af te dwingen.
Verplaats overkoepelende zorgen, zoals authenticatie en SSL-beëindiging, naar de gateway. Service-meshes en -frameworks zoals Dapr kunnen ook helpen bij veelvoorkomende kruislingse problemen, zoals mTLS-verificatie en tolerantie.
Houd domeinkennis buiten de gateway. De gateway moet aanvragen van clients verwerken en routeren zonder enige kennis van de bedrijfsregels of domeinlogica. Anders wordt de gateway een afhankelijkheid en kan deze koppeling tussen services veroorzaken.
Diensten moeten losse koppeling en een hoge functionele samenhang hebben. Functies die waarschijnlijk samen worden gewijzigd, moeten worden verpakt en samen geïmplementeerd. Als ze zich in afzonderlijke services bevinden, worden deze services nauw gekoppeld, omdat voor een wijziging in de ene service de andere service moet worden bijgewerkt. Overmatig praatgrage communicatie tussen twee diensten kan een symptoom zijn van nauwe koppeling en lage samenhang.
Gebruik pijplijnen voor continue integratie en continue implementatie (CI/CD) om testen en implementatie te automatiseren. Implementeer services onafhankelijk en bewaak de implementatiestatus.
Fouten isoleren. Gebruik tolerantiestrategieën om te voorkomen dat fouten in een service trapsgewijs worden uitgevoerd. Zie Tolerantiepatronen en Betrouwbare toepassingen ontwerpen voor meer informatie.
Gebruik chaos-engineering om de tolerantie van uw microservicearchitectuur en de bijbehorende afhankelijkheden te testen. Evalueer en verbeter hoe het systeem gedeeltelijke fouten verwerkt.
Gecentraliseerde logboekregistratie, gedistribueerde tracering (OpenTelemetry) en verzameling metrische gegevens implementeren om de waarneembaarheid te garanderen.
Antipatronen voor microservices
Wanneer u microservices ontwerpt en implementeert, treden er vaak specifieke valkuilen op die de voordelen van deze architectuurstijl kunnen ondermijnen. Door deze antipatronen te herkennen, kunnen teams kostbare fouten voorkomen en tolerantere, onderhoudbare systemen bouwen. Vermijd de volgende antipatronen:
Het implementeren van microservices zonder een grondige kennis van het bedrijfsdomein leidt tot slecht uitgelijnde servicegrenzen en ondermijnt de beoogde voordelen.
Het ontwerpen van gebeurtenissen die afhankelijk zijn van eerdere of toekomstige gebeurtenissen, schendt het principe van atomische en zelfstandige berichten. Deze afhankelijkheid dwingt consumenten om te wachten en de betrouwbaarheid van het systeem te verminderen.
Het gebruik van database-entiteiten als gebeurtenissen geeft interne servicedetails weer en brengt vaak niet de juiste bedrijfsintentie over, wat leidt tot nauw gekoppelde en onduidelijke integraties.
Het vermijden van gegevensduplicatie tegen alle kosten is een antipatroon. Het gebruik van patronen zoals gematerialiseerde weergaven om lokale kopieën te behouden, verbetert de service-autonomie en vermindert afhankelijkheden tussen services.
Door algemene gebeurtenissen te gebruiken, moeten consumenten berichten interpreteren en filteren. Deze aanpak voegt onnodige complexiteit toe en vermindert de duidelijkheid in gebeurtenisgestuurde communicatie.
Het delen van gemeenschappelijke bibliotheken of afhankelijkheden tussen microservices zorgt voor een strakke koppeling, waardoor wijzigingen riskant en wijdverspreid worden en het principe van zelfstandige services wordt tegengegaan.
Het rechtstreeks beschikbaar maken van microservices aan consumenten leidt tot strakke koppelings-, schaalbaarheidsproblemen en beveiligingsrisico's. Het gebruik van een API-gateway biedt een schoon, beheerbaar en beveiligd toegangspunt.
Door configuratiewaarden in microservices nauw te koppelen aan specifieke omgevingen, waardoor implementaties moeilijker worden. Het externaliseren van de configuratie bevordert echter flexibiliteit en de draagbaarheid van de omgeving.
Het insluiten van beveiligingslogica zoals tokenvalidatie rechtstreeks in microservices maakt hun code en onderhoud ingewikkeld. Het offloaden van beveiliging voor toegewezen onderdelen zorgt er ook voor dat services gericht en schoner blijven.
Als u veelvoorkomende microservicestaken niet abstraheert, leidt dit tot terugkerende, foutgevoelige code en beperkt u flexibiliteit. U kunt ook abstractieframeworks zoals Dapr gebruiken om de ontwikkeling te vereenvoudigen door bedrijfslogica los te koppelen van problemen met de infrastructuur.
Een microservicesarchitectuur bouwen
De volgende artikelen bevatten een gestructureerde benadering voor het ontwerpen, bouwen en gebruiken van een microservicesarchitectuur.
Domeinanalyse gebruiken: Als u veelvoorkomende valkuilen wilt voorkomen wanneer u microservices ontwerpt, gebruikt u domeinanalyse om uw microservicegrenzen te definiëren. Voer de volgende stappen uit:
- Gebruik domeinanalyse om microservices te modelleren.
- Gebruik tactische DDD om microservices te ontwerpen.
- Bepaal de grenzen van microservices.
Ontwerp de services: Microservices vereisen een gedecentraliseerde en flexibele benadering voor het ontwerpen en bouwen van toepassingen. Zie Een microservicesarchitectuur ontwerpen voor meer informatie.
Werken in productie: Omdat microservicesarchitecturen worden gedistribueerd, moet u robuuste bewerkingen hebben voor implementatie en bewaking.