Gegevensoverwegingen voor microservices
In dit artikel worden overwegingen beschreven voor het beheren van gegevens in een microservicearchitectuur. Omdat elke microservice zijn eigen gegevens beheert, zijn gegevensintegriteit en gegevensconsistentie kritieke uitdagingen.
Een basisprincipe van microservices is dat elke service zijn eigen gegevens beheert. Twee services mogen geen gegevensopslag delen. In plaats daarvan is elke service verantwoordelijk voor een eigen persoonlijke gegevensopslag, die andere services niet rechtstreeks kunnen openen.
De reden voor deze regel is om onbedoelde koppeling tussen services te voorkomen, wat kan leiden tot services die dezelfde onderliggende gegevensschema's delen. Als er een wijziging in het gegevensschema is, moet de wijziging worden gecoördineerd voor elke service die afhankelijk is van die database. Door het gegevensopslag van elke service te isoleren, kunnen we het wijzigingsbereik beperken en de flexibiliteit van echt onafhankelijke implementaties behouden. Een andere reden is dat elke microservice mogelijk zijn eigen gegevensmodellen, query's of lees-/schrijfpatronen heeft. Het gebruik van een gedeeld gegevensopslag beperkt de mogelijkheid van elk team om de gegevensopslag voor hun specifieke service te optimaliseren.

Deze aanpak leidt er natuurlijk toe polyglot persistence het gebruik van — meerdere gegevensopslagtechnologieën binnen één toepassing. Voor één service zijn mogelijk de schema-on-read-mogelijkheden van een documentdatabase vereist. Een andere heeft mogelijk de referentiële integriteit nodig die wordt geleverd door een RDBMS. Elk team kan de beste keuze voor hun service maken. Zie Use the best data store for the job (Het beste gegevensopslag gebruiken voor de taak) voor meer informatie over het algemene principe van polyglot persistence.
Notitie
Het is prima als services dezelfde fysieke databaseserver delen. Het probleem treedt op wanneer services hetzelfde schema delen of lezen en schrijven naar dezelfde set databasetabellen.
Uitdagingen
Deze gedistribueerde benadering voor het beheren van gegevens heeft enkele uitdagingen met zich mee. Ten eerste is er mogelijk redundantie in de gegevensopslag, met hetzelfde gegevensitem dat op meerdere plaatsen wordt weergegeven. Gegevens kunnen bijvoorbeeld worden opgeslagen als onderdeel van een transactie en vervolgens elders worden opgeslagen voor analyse, rapportage of archivering. Gedupliceerde of gepartliceerde gegevens kunnen leiden tot problemen met gegevensintegriteit en consistentie. Wanneer gegevensrelaties meerdere services bespannen, kunt u traditionele technieken voor gegevensbeheer niet gebruiken om de relaties af te dwingen.
Traditionele gegevensmodelleer maakt gebruik van de regel 'één feit op één plek'. Elke entiteit wordt precies één keer in het schema weergegeven. Andere entiteiten kunnen verwijzingen naar de entiteit hebben, maar deze niet dupliceren. Het voor de hand liggende voordeel van de traditionele benadering is dat updates op één plek worden aangebracht, waardoor problemen met gegevensconsistentie worden voorkomen. In een microservicearchitectuur moet u overwegen hoe updates worden doorgegeven aan services en hoe u uiteindelijke consistentie kunt beheren wanneer gegevens op meerdere plaatsen worden weergegeven zonder sterke consistentie.
Methoden voor het beheren van gegevens
Er is geen enkele benadering die in alle gevallen juist is, maar hier volgen enkele algemene richtlijnen voor het beheren van gegevens in een microservicearchitectuur.
Kies waar mogelijk voor uiteindelijke consistentie. Krijg inzicht in de plaatsen in het systeem waar u sterke consistentie of ACID-transacties nodig hebt, en de plaatsen waar uiteindelijke consistentie acceptabel is.
Wanneer u sterke consistentiegaranties nodig hebt, kan één service de bron van waarheid zijn voor een bepaalde entiteit, die beschikbaar wordt gesteld via een API. Andere services kunnen hun eigen kopie van de gegevens bevatten, of een subset van de gegevens, die uiteindelijk consistent is met de hoofdgegevens, maar niet als de bron van waarheid wordt beschouwd. Denk bijvoorbeeld aan een e-commercesysteem met een klantenserviceservice en een aanbevelingsservice. De aanbevelingsservice luistert mogelijk naar gebeurtenissen van de orderservice, maar als een klant een restitutie aanvraagt, heeft de orderservice, niet de aanbevelingsservice, de volledige transactiegeschiedenis.
Gebruik voor transacties patronen zoals Scheduler Agent Supervisor en Compensating Transaction om gegevens consistent te houden voor verschillende services. Mogelijk moet u extra gegevens opslaan die de status van een werkeenheid vastleggen die meerdere services omvat, om gedeeltelijke fouten tussen meerdere services te voorkomen. Houd bijvoorbeeld een werkitem in een duurzame wachtrij terwijl een transactie met meerdere stappen wordt uitgevoerd.
Sla alleen de gegevens op die een service nodig heeft. Een service heeft mogelijk alleen een subset met informatie over een domeinentiteit nodig. In de context Verzendgrens moeten we bijvoorbeeld weten welke klant is gekoppeld aan een bepaalde levering. Maar we hebben het factureringsadres van de klant niet nodig — dat wordt beheerd door de context Met accounts verbonden. Hier kunt u zorgvuldig nadenken over het domein en het gebruik van een DDD-benadering.
Overweeg of uw services coherent en losjes zijn gekoppeld. Als twee services voortdurend informatie met elkaar uitwisselen, wat resulteert in chatty API's, moet u mogelijk de grenzen van uw service opnieuw tekenen door twee services samen te voegen of de functionaliteit te herschrijven.
Gebruik een gebeurtenisgestuurde architectuurstijl. In deze architectuurstijl publiceert een service een gebeurtenis wanneer er wijzigingen zijn in de openbare modellen of entiteiten. Geïnteresseerde services kunnen zich abonneren op deze gebeurtenissen. Een andere service kan de gebeurtenissen bijvoorbeeld gebruiken om een ge materialiseerde weergave van de gegevens te maken die geschikter is voor het uitvoeren van query's.
Een service die eigenaar is van gebeurtenissen moet een schema publiceren dat kan worden gebruikt om het serialiseren en deserialiseren van de gebeurtenissen te automatiseren, om nauwe koppeling tussen uitgevers en abonnees te voorkomen. Overweeg het JSON-schema of een framework zoals Microsoft Bond,Protobuf of Avro.
Op grote schaal kunnen gebeurtenissen een knelpunt worden in het systeem. Overweeg daarom aggregatie of batching te gebruiken om de totale belasting te verminderen.
Voorbeeld: Gegevensopslag kiezen voor de Drone Delivery-toepassing
In de vorige artikelen in deze reeks wordt een bezorgingsservice voor drones besproken als een actief voorbeeld. Meer informatie over het scenario en de bijbehorende referentie-implementatie vindt u hier.
Samenvattend definieert deze toepassing verschillende microservices voor het plannen van leveringen per drone. Wanneer een gebruiker een nieuwe levering inplant, bevat de clientaanvraag informatie over de levering, zoals locaties voor afhalen en afleveren, en over het pakket, zoals grootte en gewicht. Deze informatie definieert een werkeenheid.
De verschillende back-endservices zijn belangrijk voor verschillende delen van de informatie in de aanvraag en hebben ook verschillende lees- en schrijfprofielen.

Leveringsservice
De leveringsservice slaat informatie op over elke levering die momenteel is gepland of wordt uitgevoerd. Het luistert naar gebeurtenissen van de drones en houdt de status bij van leveringen die worden uitgevoerd. Er worden ook domeingebeurtenissen met updates voor de leveringsstatus mee naar het domein verplaatst.
Het is te verwachten dat gebruikers vaak de status van een levering controleren terwijl ze wachten op hun pakket. Daarom vereist de Leveringsservice een gegevensopslag die de nadruk legt op doorvoer (lezen en schrijven) over langetermijnopslag. Bovendien voert de leveringsservice geen complexe query's of analyses uit. De service haalt gewoon de meest recente status op voor een bepaalde levering. Het leveringsserviceteam heeft Azure Cache voor Redis gekozen voor de hoge lees-/schrijfprestaties. De informatie die in Redis is opgeslagen, heeft een relatief korte duur. Zodra een levering is voltooid, is de Leveringsgeschiedenis-service het recordsysteem.
Leveringsgeschiedenisservice
De Leveringsgeschiedenis-service luistert naar leveringsstatusgebeurtenissen van de leveringsservice. Deze gegevens worden opgeslagen in langetermijnopslag. Er zijn twee verschillende gebruiksgevallen voor deze historische gegevens, die verschillende vereisten voor gegevensopslag hebben.
Het eerste scenario is het samenvoegen van de gegevens voor gegevensanalyse, om het bedrijf te optimaliseren of de kwaliteit van de service te verbeteren. Houd er rekening mee dat de leveringsgeschiedenisservice de werkelijke analyse van de gegevens niet kan uitvoeren. Het is alleen verantwoordelijk voor de opname en opslag. Voor dit scenario moet de opslag worden geoptimaliseerd voor gegevensanalyse voor een grote set gegevens, met behulp van een schema-on-read-benadering voor verschillende gegevensbronnen. Azure Data Lake Store is geschikt voor dit scenario. Data Lake Store is een Apache Hadoop-bestandssysteem dat compatibel is met Hadoop Distributed File System (HDFS) en is afgestemd op prestaties voor gegevensanalysescenario's.
Het andere scenario stelt gebruikers in staat om de geschiedenis van een levering op te zoeken nadat de levering is voltooid. Azure Data Lake is niet geoptimaliseerd voor dit scenario. Voor optimale prestaties raadt Microsoft aan tijdreeksgegevens op te slaan in Data Lake in mappen die zijn gepartities op datum. (Zie Azure-Data Lake Store afstemmen voor prestaties). Deze structuur is echter niet optimaal voor het opzoeken van afzonderlijke records op id. Tenzij u ook de tijdstempel kent, moet u voor een opzoekactie op id de hele verzameling scannen. Daarom slaat de leveringsgeschiedenisservice ook een subset van de historische gegevens op in Cosmos DB voor een snellere zoekactie. De records hoeven niet voor onbepaalde tijd in Cosmos DB blijven. Oudere leveringen kunnen bijvoorbeeld na — een maand worden gearchiveerd. Dit kan worden gedaan door af en toe een batchproces uit te uitvoeren.
Pakketservice
De pakketservice slaat informatie op over alle pakketten. De opslagvereisten voor het pakket zijn:
- Langetermijnopslag.
- Kan een groot aantal pakketten verwerken, wat een hoge schrijfdoorvoer vereist.
- Ondersteuning voor eenvoudige query's op pakket-id. Geen complexe joins of vereisten voor referentiële integriteit.
Omdat de pakketgegevens niet relationeel zijn, is een documentgeoriënteerde database geschikt en kan Cosmos DB hoge doorvoer bereiken met behulp van shard-verzamelingen. Het team dat aan de pakketservice werkt, is bekend met de MEAN-stack (MongoDB, Express.js, AngularJS en Node.js), dus selecteren ze de MongoDB-API voor Cosmos DB. Zo kunnen ze gebruikmaken van hun bestaande ervaring met MongoDB en profiteren ze van de voordelen van Cosmos DB, een beheerde Azure-service.
Volgende stappen
Meer informatie over ontwerppatronen waarmee u een aantal veelvoorkomende uitdagingen in een microservicearchitectuur kunt verhelpen.