Waarom een microservicesbenadering gebruiken voor het bouwen van toepassingen
Voor softwareontwikkelaars is het factoren van een toepassing in onderdelen niets nieuws. Normaal gesproken wordt een gelaagde benadering gebruikt, met een back-endarchief, bedrijfslogica in de middelste laag en een front-endgebruikersinterface (UI). Wat de afgelopen jaren is veranderd, is dat ontwikkelaars gedistribueerde toepassingen bouwen voor de cloud.
Hier volgen enkele veranderende bedrijfsbehoeften:
- Een service die op schaal is gebouwd en beheerd om klanten in nieuwe geografische regio's te bereiken.
- Snellere levering van functies en mogelijkheden om op een flexibele manier te reageren op de eisen van klanten.
- Verbeterd resourcegebruik om de kosten te verlagen.
Deze zakelijke behoeften zijn van invloed op de wijze waarop we toepassingen bouwen.
Zie Microservices: Een toepassings revolutie mogelijk gemaakt door de cloud voor meer informatie over de Azure-benadering van microservices.
Monolithische versus microservices-ontwerpbenadering
Toepassingen ontwikkelen zich in de loop van de tijd. Succesvolle toepassingen ontwikkelen zich door nuttig te zijn voor mensen. Mislukte toepassingen ontwikkelen zich niet en worden uiteindelijk afgeschaft. Hier is de vraag: hoeveel weet u vandaag over uw vereisten en wat ze in de toekomst zullen zijn? Stel dat u een rapportagetoepassing bouwt voor een afdeling in uw bedrijf. U weet zeker dat de toepassing alleen binnen het bereik van uw bedrijf van toepassing is en dat de rapporten niet lang worden bewaard. Uw aanpak verschilt van die van het bouwen van een service die video-inhoud levert aan tientallen miljoenen klanten.
Soms is het de drijvende factor om iets buiten de deur te krijgen als bewijs van concept. U weet dat de toepassing later opnieuw kan worden ontworpen. Er is weinig zin in over-engineering iets dat nooit wordt gebruikt. Aan de andere kant, wanneer bedrijven bouwen voor de cloud, is de verwachting groei en gebruik. Groei en schaal zijn onvoorspelbaar. We willen snel prototypen maken terwijl we ook weten dat we op een pad zijn dat toekomstige succes kan afhandelen. Dit is de lean startup-benadering: bouwen, meten, leren en herhalen.
Tijdens het client-/servertijdperk richten we ons meestal op het bouwen van gelaagde toepassingen met behulp van specifieke technologieën in elke laag. De term monolithische toepassing is ontstaan om deze benaderingen te beschrijven. De interfaces waren meestal tussen de lagen en er werd een nauwer gekoppeld ontwerp gebruikt tussen onderdelen binnen elke laag. Ontwikkelaars hebben klassen ontworpen en gefactoreerd die zijn gecompileerd in bibliotheken en die zijn gekoppeld aan enkele uitvoerbare bestanden en DLL's.
Er zijn voordelen voor een monolithische ontwerpbenadering. Monolithische toepassingen zijn vaak eenvoudiger te ontwerpen en aanroepen tussen onderdelen zijn sneller omdat deze aanroepen vaak over interprocescommunicatie (IPC) gaan. Bovendien test iedereen één product, dat meestal een efficiënter gebruik van human resources is. Het nadeel is dat er een strakke koppeling is tussen gelaagde lagen en dat u afzonderlijke onderdelen niet kunt schalen. Als u oplossingen of upgrades moet uitvoeren, moet u wachten totdat anderen hun tests hebben voltooid. Het is moeilijker om flexibel te zijn.
Microservices hebben betrekking op deze nadelen en zijn nauwer afgestemd op de voorgaande bedrijfsvereisten. Maar ze hebben ook zowel voordelen als verplichtingen. De voordelen van microservices zijn dat elke service doorgaans eenvoudigere bedrijfsfunctionaliteit inkapselt, die u onafhankelijk van elkaar kunt uitschalen, testen, implementeren en beheren. Een belangrijk voordeel van een microservicesbenadering is dat teams meer worden gedreven door bedrijfsscenario's dan door technologie. Kleinere teams ontwikkelen een microservice op basis van een klantscenario en kunnen hiervoor elke gewenste technologie gebruiken.
Met andere woorden, de organisatie hoeft technologie niet te standaardiseren om microservicetoepassingen te onderhouden. Individuele teams die eigenaar zijn van services kunnen voor hen zinvol zijn op basis van teamexpertise of wat het meest geschikt is om het probleem op te lossen. In de praktijk is een set aanbevolen technologieën, zoals een bepaald NoSQL-archief of webtoepassingsframework, de voorkeur.
Het nadeel van microservices is dat u meer afzonderlijke entiteiten moet beheren en te maken hebt met complexere implementaties en versiebeheer. Netwerkverkeer tussen de microservices neemt toe, net als de bijbehorende netwerklatenties. Veel praatige, gedetailleerde services kunnen een nachtmerrie van de prestaties veroorzaken. Zonder hulpprogramma's om u te helpen deze afhankelijkheden weer te geven, is het moeilijk om het hele systeem te zien.
Standaarden zorgen ervoor dat de microservicesbenadering werkt door aan te geven hoe u alleen de dingen die u nodig hebt van een service kunt communiceren en tolereren, in plaats van starre contracten. Het is belangrijk om deze contracten vooraf in het ontwerp te definiëren, omdat services onafhankelijk van elkaar worden bijgewerkt. Een andere beschrijving die is ontworpen voor het ontwerpen met een microservicesbenadering is "verfijnde servicegeoriënteerde architectuur (SOA)."
Op de eenvoudigste manier gaat het om een ontkoppelde federatie van services, met onafhankelijke wijzigingen in elke en overeengekomen normen voor communicatie.
Naarmate er meer cloudtoepassingen worden geproduceerd, hebben mensen ontdekt dat deze ontleding van de algehele toepassing in onafhankelijke, scenariogerichte services een betere benadering op de lange termijn is.
Vergelijking tussen benaderingen voor het ontwikkelen van toepassingen
Een monolithische toepassing bevat domeinspecifieke functionaliteit en wordt normaal gesproken onderverdeeld in functionele lagen zoals web, bedrijf en gegevens.
U kunt een monolithische toepassing schalen door deze te klonen op meerdere servers/virtuele machines/containers.
Een microservicetoepassing scheidt functionaliteit in afzonderlijke kleinere services.
De microservicesbenadering wordt uitgeschaald door elke service onafhankelijk te implementeren, waardoor exemplaren van deze services worden gemaakt op servers/virtuele machines/containers.
Ontwerpen met een microservicesbenadering is niet geschikt voor alle projecten, maar is beter afgestemd op de eerder beschreven bedrijfsdoelstellingen. Beginnen met een monolithische benadering kan zinvol zijn als u weet dat u de code later opnieuw kunt bewerken in een microservicesontwerp. Meestal begint u met een monolithische toepassing en breekt u deze langzaam op in fasen, te beginnen met de functionele gebieden die schaalbaarder of flexibeler moeten zijn.
Wanneer u een microservicesbenadering gebruikt, stelt u uw toepassing op van veel kleine services. Deze services worden uitgevoerd in containers die zijn geïmplementeerd in een cluster van machines. Kleinere teams ontwikkelen een service die zich richt op een scenario en onafhankelijk testen, versie, implementeren en schalen van elke service, zodat de hele toepassing zich kan ontwikkelen.
Wat is een microservice?
Er zijn verschillende definities van microservices. Maar de meeste van deze kenmerken van microservices worden algemeen geaccepteerd:
- Een klant- of bedrijfsscenario inkapselen. Welk probleem lost u op?
- Ontwikkeld door een klein technisch team.
- Geschreven in elke programmeertaal, met behulp van elk framework.
- Bestaat uit code en eventueel een status, die beide onafhankelijk zijn geversied, geïmplementeerd en geschaald.
- Interactie met andere microservices via goed gedefinieerde interfaces en protocollen.
- Unieke namen (URL's) hebben die worden gebruikt om hun locatie op te lossen.
- Blijf consistent en beschikbaar in aanwezigheid van fouten.
Dit optellen:
Microservicetoepassingen bestaan uit kleine, onafhankelijke en schaalbare klantgerichte services die met elkaar communiceren via standaardprotocollen met goed gedefinieerde interfaces.
Geschreven in elke programmeertaal, met behulp van elk framework
Als ontwikkelaars willen we vrij zijn om een taal of framework te kiezen, afhankelijk van onze vaardigheden en de behoeften van de service die we maken. Voor sommige services kunt u de prestatievoordelen van C++ boven alles waarderen. Voor anderen is het gemak van beheerde ontwikkeling dat u krijgt van C# of Java misschien belangrijker. In sommige gevallen moet u mogelijk een specifieke partnerbibliotheek, gegevensopslagtechnologie of methode gebruiken om de service beschikbaar te maken voor clients.
Nadat u een technologie hebt gekozen, moet u rekening houden met het operationele of levenscyclusbeheer en het schalen van de service.
Hiermee staat u toe dat code en status onafhankelijk van elkaar worden geversied, geïmplementeerd en geschaald
Ongeacht hoe u uw microservices schrijft, de code en eventueel de status, moet onafhankelijk worden geïmplementeerd, bijgewerkt en geschaald. Dit probleem is moeilijk op te lossen omdat het neer komt op uw keuze aan technologieën. Voor het schalen is het lastig om te begrijpen hoe u zowel de code als de status partitioneert (of shard). Wanneer de code en status verschillende technologieën gebruiken, wat tegenwoordig gebruikelijk is, moeten de implementatiescripts voor uw microservice beide kunnen schalen. Deze scheiding gaat ook over flexibiliteit en flexibiliteit, zodat u enkele van de microservices kunt upgraden zonder dat u ze allemaal tegelijk hoeft te upgraden.
Laten we even terugkeren naar onze vergelijking van de monolithische en microservicesmethoden. In dit diagram ziet u de verschillen in de benaderingen voor het opslaan van de status:
Statusopslag voor de twee benaderingen
De monolithische benadering aan de linkerkant heeft één database en lagen van specifieke technologieën.
De microservicesbenadering heeft aan de rechterkant een grafiek van onderling verbonden microservices waarbij de status doorgaans is afgestemd op de microservice en verschillende technologieën worden gebruikt.
In een monolithische benadering gebruikt de toepassing doorgaans één database. Het voordeel van het gebruik van één database is dat deze zich op één locatie bevindt, waardoor het eenvoudig te implementeren is. Elk onderdeel kan één tabel hebben om de status op te slaan. Teams moeten strikt afzonderlijke statussen hebben, wat een uitdaging is. Iemand is onvermijdelijk geneigd om een kolom toe te voegen aan een bestaande klanttabel, een join tussen tabellen uit te voeren en afhankelijkheden te maken op de opslaglaag. Nadat dit is gebeurd, kunt u afzonderlijke onderdelen niet schalen.
In de microservicesbenadering beheert en slaat elke service een eigen status op. Elke service is verantwoordelijk voor het schalen van zowel code als de status om te voldoen aan de vereisten van de service. Een nadeel is dat wanneer u weergaven of query's van de gegevens van uw toepassing moet maken, u query's moet uitvoeren in meerdere statusarchieven. Dit probleem wordt meestal opgelost door een afzonderlijke microservice waarmee een weergave wordt opgebouwd over een verzameling microservices. Als u meerdere oneigenlijke query's op de gegevens wilt uitvoeren, kunt u overwegen om de gegevens van elke microservice te schrijven naar een datawarehousingservice voor offlineanalyses.
Microservices zijn versiebeheer. Het is mogelijk dat verschillende versies van een microservice naast elkaar worden uitgevoerd. Een nieuwere versie van een microservice kan mislukken tijdens een upgrade en moet worden teruggedraaid naar een eerdere versie. Versiebeheer is ook handig voor A/B-tests, waarbij verschillende gebruikers verschillende versies van de service ervaren. Het is bijvoorbeeld gebruikelijk om een microservice te upgraden voor een specifieke set klanten om nieuwe functionaliteit te testen voordat deze breder wordt geïmplementeerd.
Communiceert met andere microservices via goed gedefinieerde interfaces en protocollen
In de afgelopen 10 jaar is uitgebreide informatie gepubliceerd over communicatiepatronen in servicegerichte architecturen. Over het algemeen maakt servicecommunicatie gebruik van een REST-benadering met HTTP- en TCP-protocollen en XML of JSON als serialisatie-indeling. Vanuit het perspectief van een interface gaat het om het nemen van een webontwerpbenadering. Maar niets mag u stoppen met het gebruik van binaire protocollen of uw eigen gegevensindelingen. Houd er rekening mee dat mensen een moeilijkere tijd hebben om uw microservices te gebruiken als deze protocollen en indelingen niet open beschikbaar zijn.
Heeft een unieke naam (URL) gebruikt om de locatie op te lossen
Uw microservice moet adresseerbaar zijn, ongeacht waar deze wordt uitgevoerd. Als u nadenkt over machines en welke een bepaalde microservice uitvoert, kunnen dingen snel slecht gaan.
Op dezelfde manier dat DNS een bepaalde URL naar een bepaalde computer oplost, heeft uw microservice een unieke naam nodig, zodat de huidige locatie kan worden gedetecteerd. Microservices hebben adresseerbare namen nodig die onafhankelijk zijn van de infrastructuur waarop ze worden uitgevoerd. Dit impliceert dat er een interactie is tussen hoe uw service wordt geïmplementeerd en hoe deze wordt gedetecteerd, omdat er een serviceregister moet zijn. Wanneer een computer uitvalt, moet de registerservice u laten weten waar de service naartoe is verplaatst.
Blijft consistent en beschikbaar in aanwezigheid van fouten
Het oplossen van onverwachte fouten is een van de moeilijkste problemen, met name in een gedistribueerd systeem. Veel van de code die we schrijven als ontwikkelaars is voor het verwerken van uitzonderingen. Tijdens het testen besteden we ook de meeste tijd aan het verwerken van uitzonderingen. Het proces is meer betrokken dan het schrijven van code voor het afhandelen van fouten. Wat gebeurt er wanneer de computer waarop de microservice wordt uitgevoerd, mislukt? U moet de fout detecteren. Dit is een moeilijk probleem. Maar u moet ook uw microservice opnieuw opstarten.
Voor beschikbaarheid moet een microservice bestand zijn tegen fouten en opnieuw opstarten op een andere computer. Naast deze tolerantievereisten mogen gegevens niet verloren gaan en moeten gegevens consistent blijven.
Tolerantie is moeilijk te bereiken wanneer er fouten optreden tijdens een toepassingsupgrade. De microservice, die werkt met het implementatiesysteem, hoeft niet te worden hersteld. Er moet worden bepaald of deze verder kan gaan naar de nieuwere versie of terug kan gaan naar een eerdere versie om een consistente status te behouden. U moet rekening houden met een paar vragen, zoals of er voldoende machines beschikbaar zijn om verder te gaan en hoe u eerdere versies van de microservice kunt herstellen. Als u deze beslissingen wilt nemen, hebt u de microservice nodig om statusinformatie te verzenden.
Rapporteert de status en diagnostische gegevens
Het lijkt misschien duidelijk en het wordt vaak over het hoofd gezien, maar een microservice moet de status en diagnose rapporteren. Anders hebt u weinig inzicht in de status vanuit het perspectief van bewerkingen. Het correleren van diagnostische gebeurtenissen in een set onafhankelijke services en het omgaan met scheeftrekken van machineklokken om de gebeurtenisvolgorde te begrijpen, is lastig. Op dezelfde manier als u met een microservice communiceert over overeengekomen protocollen en gegevensindelingen, moet u standaardiseren hoe u de status en diagnostische gebeurtenissen registreert die uiteindelijk in een gebeurtenisarchief terechtkomen voor het uitvoeren en weergeven van query's. Met een microservicesbenadering moeten verschillende teams het eens zijn over één indeling voor logboekregistratie. Er moet een consistente benadering zijn voor het weergeven van diagnostische gebeurtenissen in de toepassing als geheel.
De status verschilt van diagnostische gegevens. De status gaat over de microservice die de huidige status rapporteert om passende acties uit te voeren. Een goed voorbeeld is het werken met upgrade- en implementatiemechanismen om de beschikbaarheid te behouden. Hoewel een service momenteel niet in orde is vanwege een procescrash of het opnieuw opstarten van de machine, is de service mogelijk nog steeds operationeel. Het laatste wat u nodig hebt, is om de situatie erger te maken door een upgrade te starten. De beste aanpak is om eerst te onderzoeken of tijd te bieden voordat de microservice kan worden hersteld. Gezondheidsgebeurtenissen van een microservice helpen ons weloverwogen beslissingen te nemen en, in feite, zelfhersteldiensten te creëren.
Richtlijnen voor het ontwerpen van microservices in Azure
Ga naar het Azure-architectuurcentrum voor hulp bij het ontwerpen en bouwen van microservices in Azure.
Service Fabric als microservicesplatform
Azure Service Fabric is ontstaan toen Microsoft overstapte van het leveren van boxed producten, die doorgaans monolithisch waren, tot het leveren van services. De ervaring van het bouwen en gebruiken van grote services, zoals Azure SQL Database en Azure Cosmos DB, vormgegeven Service Fabric. Het platform is in de loop van de tijd ontwikkeld naarmate er meer services zijn aangenomen. Service Fabric moest niet alleen worden uitgevoerd in Azure, maar ook in zelfstandige Windows Server-implementaties.
Het doel van Service Fabric is het oplossen van de harde problemen van het bouwen en uitvoeren van een service en het efficiënt gebruiken van infrastructuurresources, zodat teams bedrijfsproblemen kunnen oplossen met behulp van een microservicesbenadering.
Service Fabric helpt u bij het bouwen van toepassingen die gebruikmaken van een microservicesbenadering door het volgende te bieden:
- Een platform dat systeemservices biedt voor het implementeren, upgraden, detecteren en opnieuw starten van mislukte services, het detecteren van services, het routeren van berichten, het beheren van de status en het bewaken van de status.
- De mogelijkheid om toepassingen te implementeren die worden uitgevoerd in containers of als processen. Service Fabric is een container en procesorchestrator.
- Productieve programmeer-API's om u te helpen bij het bouwen van toepassingen als microservices: ASP.NET Core, Reliable Actors en Reliable Services. U kunt bijvoorbeeld status- en diagnosegegevens ophalen of profiteren van ingebouwde hoge beschikbaarheid.
Service Fabric is agnostisch over hoe u uw service bouwt en u kunt elke technologie gebruiken. Maar het biedt wel ingebouwde programmeer-API's waarmee u eenvoudiger microservices kunt bouwen.
Bestaande toepassingen migreren naar Service Fabric
Met Service Fabric kunt u bestaande code hergebruiken en moderniseren met nieuwe microservices. Er zijn vijf fasen voor het moderniseren van toepassingen en u kunt in elke fase starten en stoppen. De fasen zijn:
- Begin met een traditionele monolithische toepassing.
- Migreren. Gebruik containers of uitvoerbare gastbestanden om bestaande code in Service Fabric te hosten.
- Moderniseren. Voeg nieuwe microservices toe naast bestaande containercode.
- Innoveer. Verbreek de monolithische toepassing in microservices op basis van behoefte.
- Toepassingen transformeren in microservices. Bestaande monolithische toepassingen transformeren of nieuwe greenfield-toepassingen bouwen.
Vergeet niet dat u bij een van deze fasen kunt beginnen en stoppen. U hoeft niet verder te gaan met de volgende fase.
Laten we eens kijken naar voorbeelden voor elk van deze fasen.
Migreren
Om twee redenen migreren veel bedrijven bestaande monolithische toepassingen naar containers:
- Kostenreductie, hetzij vanwege consolidatie en verwijdering van bestaande hardware of door actieve toepassingen met een hogere dichtheid.
- Een consistent implementatiecontract tussen ontwikkeling en bewerkingen.
Kostenreducties zijn eenvoudig. Bij Microsoft worden veel bestaande toepassingen in een container geplaatst, wat leidt tot miljoenen dollars aan besparingen. Consistente implementatie is moeilijker te evalueren, maar is even belangrijk. Dit betekent dat ontwikkelaars de technologieën kunnen kiezen die bij hen passen, maar bewerkingen accepteren slechts één methode voor het implementeren en beheren van de toepassingen. Het vermindert bewerkingen van het omgaan met de complexiteit van het ondersteunen van verschillende technologieën zonder ontwikkelaars te dwingen om alleen bepaalde technologieën te kiezen. In wezen wordt elke toepassing in een container geplaatst in zelf-ingesloten implementatieinstallatiekopieën.
Veel organisaties stoppen hier. Ze hebben al de voordelen van containers en Service Fabric biedt de volledige beheerervaring, waaronder implementatie, upgrades, versiebeheer, terugdraaiacties en statuscontrole.
Moderniseren
Modernisering is de toevoeging van nieuwe services naast bestaande containercode. Als u nieuwe code gaat schrijven, kunt u het beste kleine stappen in het pad naar microservices uitvoeren. Dit kan betekenen dat u een nieuw REST API-eindpunt of nieuwe bedrijfslogica toevoegt. Op deze manier start u het proces voor het bouwen van nieuwe microservices en oefent u met het ontwikkelen en implementeren ervan.
Innoveren
Een microservicesbenadering biedt ruimte voor veranderende bedrijfsbehoeften. In deze fase moet u beslissen of u de monolithische toepassing wilt splitsen in services of innoveren. Een klassiek voorbeeld hier is wanneer een database die u als werkstroomwachtrij gebruikt, een knelpunt voor verwerking wordt. Naarmate het aantal werkstroomaanvragen toeneemt, moet het werk worden gedistribueerd voor schaalaanpassing. Neem dat specifieke deel van de toepassing dat niet wordt geschaald of die vaker moet worden bijgewerkt, en splitst deze op als een microservice en innoveren.
Toepassingen transformeren in microservices
In deze fase bestaat uw toepassing volledig uit (of opgesplitst in) microservices. Om dit punt te bereiken, hebt u de microservicesreis gemaakt. U kunt hier beginnen, maar om dit te doen zonder een microservicesplatform om u te helpen een aanzienlijke investering te doen.
Zijn microservices geschikt voor mijn toepassing?
Misschien. Bij Microsoft realiseerden veel van hen, naarmate meer teams om zakelijke redenen voor de cloud begonnen te bouwen, de voordelen van het nemen van een microservice-achtige benadering. Bing gebruikt bijvoorbeeld al jaren microservices. Voor andere teams was de microservicesbenadering nieuw. Teams vonden dat er moeilijk problemen waren om buiten hun kerngebieden van kracht op te lossen. Daarom kreeg Service Fabric tractie als technologie voor het bouwen van services.
Het doel van Service Fabric is om de complexiteit van het bouwen van microservicetoepassingen te verminderen, zodat u niet zoveel kostbare herontwerpen hoeft te doorlopen. Begin op kleine schaal, schaal indien nodig, verwijder services, voeg nieuwe services toe en ontwikkel met klantgebruik. We weten ook dat er veel andere problemen zijn die nog moeten worden opgelost om microservices toegankelijker te maken voor de meeste ontwikkelaars. Containers en het actorprogrammeermodel zijn voorbeelden van kleine stappen in die richting. We zijn er zeker van dat er meer innovaties ontstaan om een microservicesbenadering eenvoudiger te maken.