Het API-gatewaypatroon versus de directe client-naar-microservice-communicatie
Tip
Deze inhoud is een fragment uit het eBook, .NET Microservices Architecture for Containerized .NET Applications, beschikbaar op .NET Docs of als een gratis downloadbare PDF die offline kan worden gelezen.
In een microservicesarchitectuur maakt elke microservice een set (meestal) fijnmazige eindpunten beschikbaar. Dit feit kan van invloed zijn op de communicatie van de client naar microservice, zoals wordt uitgelegd in deze sectie.
Directe client-naar-microservicecommunicatie
Een mogelijke benadering is het gebruik van een directe client-naar-microservice-communicatiearchitectuur. Bij deze benadering kan een client-app rechtstreeks aanvragen indienen bij sommige microservices, zoals weergegeven in afbeelding 4-12.
Afbeelding 4-12. Een directe communicatiearchitectuur voor client-naar-microservice gebruiken
Bij deze benadering heeft elke microservice een openbaar eindpunt, soms met een andere TCP-poort voor elke microservice. Een voorbeeld van een URL voor een bepaalde service kan de volgende URL in Azure zijn:
http://eshoponcontainers.westus.cloudapp.azure.com:88/
In een productieomgeving op basis van een cluster zou die URL worden toegewezen aan de load balancer die in het cluster wordt gebruikt, die de aanvragen vervolgens over de microservices distribueert. In productieomgevingen kunt u een ADC (Application Delivery Controller) hebben, zoals Azure-toepassing Gateway tussen uw microservices en internet. Deze laag fungeert als een transparante laag die niet alleen taakverdeling uitvoert, maar uw services beveiligt door SSL-beëindiging aan te bieden. Deze aanpak verbetert de belasting van uw hosts door CPU-intensieve SSL-beëindiging en andere routeringstaken naar de Azure-toepassing Gateway te offloaden. In elk geval zijn een load balancer en ADC transparant vanuit het oogpunt van een logische toepassingsarchitectuur.
Een directe client-naar-microservice-communicatiearchitectuur kan goed genoeg zijn voor een kleine microservicetoepassing, met name als de client-app een webtoepassing aan de serverzijde is, zoals een ASP.NET MVC-app. Wanneer u echter grote en complexe op microservices gebaseerde toepassingen bouwt (bijvoorbeeld bij het verwerken van tientallen microservicetypen), en vooral wanneer de client-apps externe mobiele apps of beveiligd-WACHTWOORDVERIFICATIE-webtoepassingen zijn, krijgt die aanpak enkele problemen.
Houd rekening met de volgende vragen bij het ontwikkelen van een grote toepassing op basis van microservices:
- Hoe kunnen client-apps het aantal aanvragen naar de back-end minimaliseren en chattycommunicatie naar meerdere microservices verminderen?
Interactie met meerdere microservices om één ui-scherm te bouwen, verhoogt het aantal retouren via internet. Deze benadering verhoogt de latentie en complexiteit aan de gebruikersinterfacezijde. In het ideale geval moeten antwoorden efficiënt worden geaggregeerd aan de serverzijde. Deze aanpak vermindert de latentie, omdat meerdere stukjes gegevens parallel terugkomen en sommige gebruikersinterface gegevens kan weergeven zodra deze gereed zijn.
- Hoe kunt u kruislingse problemen afhandelen, zoals autorisatie, gegevenstransformaties en dynamische aanvraagverzending?
Het implementeren van beveiligings- en kruislingse problemen, zoals beveiliging en autorisatie op elke microservice, kan aanzienlijke ontwikkelingsinspanningen vereisen. Een mogelijke aanpak is dat deze services binnen de Docker-host of het interne cluster worden gebruikt om de directe toegang tot deze services van buitenaf te beperken en deze kruislingse zorgen op een centrale locatie te implementeren, zoals een API-gateway.
- Hoe kunnen client-apps communiceren met services die gebruikmaken van niet-internetvriendelijke protocollen?
Protocollen die worden gebruikt aan de serverzijde (zoals AMQP of binaire protocollen) worden niet ondersteund in client-apps. Aanvragen moeten daarom worden uitgevoerd via protocollen zoals HTTP/HTTPS en daarna worden vertaald naar de andere protocollen. Een man-in-the-middle aanpak kan in deze situatie helpen.
- Hoe kunt u een gevel vormgeven die speciaal is gemaakt voor mobiele apps?
De API van meerdere microservices is mogelijk niet goed ontworpen voor de behoeften van verschillende clienttoepassingen. De behoeften van een mobiele app kunnen bijvoorbeeld afwijken van de behoeften van een web-app. Voor mobiele apps moet u mogelijk nog verder optimaliseren, zodat gegevensreacties efficiënter kunnen zijn. U kunt deze functionaliteit uitvoeren door gegevens van meerdere microservices samen te voegen en één set gegevens te retourneren, en soms eventuele gegevens in het antwoord te elimineren dat niet nodig is voor de mobiele app. En natuurlijk kunt u die gegevens comprimeren. Ook hier kan een gevel of API tussen de mobiele app en de microservices handig zijn voor dit scenario.
Waarom API-gateways overwegen in plaats van directe client-naar-microservice-communicatie
In een microservicesarchitectuur moeten de client-apps doorgaans functionaliteit van meer dan één microservice gebruiken. Als dat verbruik rechtstreeks wordt uitgevoerd, moet de client meerdere aanroepen naar microservice-eindpunten verwerken. Wat gebeurt er wanneer de toepassing zich ontwikkelt en nieuwe microservices worden geïntroduceerd of bestaande microservices worden bijgewerkt? Als uw toepassing veel microservices heeft, kan het verwerken van zoveel eindpunten van de client-apps een nachtmerrie zijn. Omdat de client-app zou worden gekoppeld aan deze interne eindpunten, kan het ontwikkelen van de microservices in de toekomst een grote impact voor de client-apps veroorzaken.
Daarom kan het hebben van een tussenliggend niveau of een laag van indirectie (Gateway) handig zijn voor toepassingen op basis van microservices. Als u geen API-gateways hebt, moeten de client-apps aanvragen rechtstreeks naar de microservices verzenden en problemen veroorzaken, zoals de volgende problemen:
Koppeling: Zonder het API Gateway-patroon zijn de client-apps gekoppeld aan de interne microservices. De client-apps moeten weten hoe de verschillende gebieden van de toepassing worden opgesplitst in microservices. Bij het ontwikkelen en herstructureren van de interne microservices zijn deze acties van invloed op onderhoud omdat ze wijzigingen veroorzaken die fouten veroorzaken in de client-apps vanwege de directe verwijzing naar de interne microservices van de client-apps. Client-apps moeten regelmatig worden bijgewerkt, waardoor de oplossing moeilijker kan worden ontwikkeld.
Te veel retouren: Voor één pagina/scherm in de client-app zijn mogelijk meerdere aanroepen naar meerdere services vereist. Deze benadering kan leiden tot meerdere retouren van netwerken tussen de client en de server, waardoor aanzienlijke latentie wordt toegevoegd. Aggregatie die in een tussenliggend niveau wordt verwerkt, kan de prestaties en gebruikerservaring voor de client-app verbeteren.
Beveiligingsproblemen: Zonder een gateway moeten alle microservices worden blootgesteld aan de 'externe wereld', waardoor het aanvalsoppervlak groter wordt dan als u interne microservices verbergt die niet rechtstreeks door de client-apps worden gebruikt. Hoe kleiner de kwetsbaarheid voor aanvallen is, hoe veiliger uw toepassing kan zijn.
Cross-cutting zorgen: Elke openbaar gepubliceerde microservice moet zorgen afhandelen, zoals autorisatie en SSL. In veel situaties kunnen deze problemen in één laag worden afgehandeld, zodat de interne microservices worden vereenvoudigd.
Wat is het API Gateway-patroon?
Wanneer u grote of complexe microservicetoepassingen ontwerpt en bouwt met meerdere client-apps, kan een goede benadering een API-gateway zijn. Dit patroon is een service die één toegangspunt biedt voor bepaalde groepen microservices. Het is vergelijkbaar met het patroon Gevel van objectgeoriënteerd ontwerp, maar in dit geval maakt het deel uit van een gedistribueerd systeem. Het API Gateway-patroon wordt ook wel de 'back-end voor front-end' (BFF) genoemd, omdat u deze bouwt terwijl u nadenkt over de behoeften van de client-app.
Daarom bevindt de API-gateway zich tussen de client-apps en de microservices. Het fungeert als een omgekeerde proxy, routeringsaanvragen van clients naar services. Het kan ook andere geavanceerde functies bieden, zoals verificatie, SSL-beëindiging en cache.
In afbeelding 4-13 ziet u hoe een aangepaste API-gateway kan passen in een vereenvoudigde architectuur op basis van microservices met slechts een paar microservices.
Afbeelding 4-13. Een API-gateway gebruiken die is geïmplementeerd als een aangepaste service
Apps maken verbinding met één eindpunt, de API-gateway, die is geconfigureerd voor het doorsturen van aanvragen naar afzonderlijke microservices. In dit voorbeeld wordt de API-gateway geïmplementeerd als een aangepaste ASP.NET Core WebHost-service die als een container wordt uitgevoerd.
Het is belangrijk om te benadrukken dat u in dat diagram één aangepaste API Gateway-service gebruikt die gericht is op meerdere en verschillende client-apps. Dat kan een belangrijk risico zijn omdat uw API Gateway-service groeit en zich ontwikkelt op basis van veel verschillende vereisten van de client-apps. Uiteindelijk wordt het bloed vanwege deze verschillende behoeften en kan het effectief vergelijkbaar zijn met een monolithische toepassing of monolithische service. Daarom wordt het sterk aanbevolen om de API-gateway te splitsen in meerdere services of meerdere kleinere API-gateways, één per formulierfactortype voor client-apps.
U moet voorzichtig zijn bij het implementeren van het API Gateway-patroon. Meestal is het geen goed idee om één API-gateway te hebben die alle interne microservices van uw toepassing samenvoegt. Als dat het geval is, fungeert het als een monolithische aggregator of orchestrator en schendt het microservice-autonomie door alle microservices te koppelen.
Daarom moeten de API-gateways worden gescheiden op basis van bedrijfsgrenzen en de client-apps en niet fungeren als één aggregator voor alle interne microservices.
Wanneer u de API Gateway-laag splitst in meerdere API-gateways, als uw toepassing meerdere client-apps heeft, kan dit een primaire draai zijn bij het identificeren van de typen API-gateways, zodat u een andere gevel kunt hebben voor de behoeften van elke client-app. Dit geval is een patroon met de naam 'Back-end voor Front-end' (BFF), waarbij elke API-gateway een andere API kan bieden die is afgestemd op elk type client-app, mogelijk zelfs op basis van de clientformulierfactor door specifieke adaptercode te implementeren die onder meerdere interne microservices wordt aangeroepen, zoals wordt weergegeven in de volgende afbeelding:
Afbeelding 4-13.1. Meerdere aangepaste API-gateways gebruiken
Afbeelding 4-13.1 toont API-gateways die zijn gescheiden door clienttype; één voor mobiele clients en één voor webclients. Een traditionele web-app maakt verbinding met een MVC-microservice die gebruikmaakt van de web-API-gateway. In het voorbeeld ziet u een vereenvoudigde architectuur met meerdere verfijnde API-gateways. In dit geval zijn de grenzen die voor elke API-gateway worden geïdentificeerd, uitsluitend gebaseerd op het patroon 'Back-end voor front-end' (BFF), dus alleen op basis van de API die per client-app nodig is. Maar in grotere toepassingen moet u ook verder gaan en andere API-gateways maken op basis van bedrijfsgrenzen als tweede ontwerpdraaipunt.
Belangrijkste functies in het API Gateway-patroon
Een API-gateway kan meerdere functies bieden. Afhankelijk van het product kan het uitgebreidere of eenvoudigere functies bieden, maar de belangrijkste en fundamentele functies voor elke API Gateway zijn de volgende ontwerppatronen:
Omgekeerde proxy- of gatewayroutering. De API-gateway biedt een omgekeerde proxy voor het omleiden of routeren van aanvragen (laag 7-routering, meestal HTTP-aanvragen) naar de eindpunten van de interne microservices. De gateway biedt één eindpunt of URL voor de client-apps en wijst de aanvragen vervolgens intern toe aan een groep interne microservices. Deze routeringsfunctie helpt bij het loskoppelen van de client-apps van de microservices, maar het is ook handig wanneer u een monolithische API moderniseert door de API-gateway tussen de monolithische API en de client-apps te zetten. Vervolgens kunt u nieuwe API's toevoegen als nieuwe microservices terwijl u de verouderde monolithische API nog steeds gebruikt totdat deze in de toekomst is gesplitst in veel microservices. Vanwege de API-gateway zien de client-apps niet of de API's die worden gebruikt, worden geïmplementeerd als interne microservices of een monolithische API en belangrijker, bij het ontwikkelen en herstructureren van de monolithische API in microservices, dankzij de API Gateway-routering, worden client-apps niet beïnvloed door een URI-wijziging.
Zie gatewayrouteringspatroon voor meer informatie.
Aggregatie aanvragen. Als onderdeel van het gatewaypatroon kunt u meerdere clientaanvragen (meestal HTTP-aanvragen) aggregeren die gericht zijn op meerdere interne microservices in één clientaanvraag. Dit patroon is vooral handig wanneer een clientpagina/scherm informatie van verschillende microservices nodig heeft. Met deze methode verzendt de client-app één aanvraag naar de API-gateway die verschillende aanvragen naar de interne microservices verzendt en vervolgens de resultaten samenvoegt en alles terugstuurt naar de client-app. Het belangrijkste voordeel en doel van dit ontwerppatroon is om de chattiness tussen de client-apps en de back-end-API te verminderen, wat vooral belangrijk is voor externe apps uit het datacenter waar de microservices zich bevinden, zoals mobiele apps of aanvragen die afkomstig zijn van BEVEILIGD-WACHTWOORDVERIFICATIE-apps die afkomstig zijn van JavaScript in externe browsers van clients. Voor normale web-apps die de aanvragen uitvoeren in de serveromgeving (zoals een ASP.NET Core MVC-web-app), is dit patroon niet zo belangrijk omdat de latentie veel kleiner is dan voor externe client-apps.
Afhankelijk van het API Gateway-product dat u gebruikt, kan deze aggregatie mogelijk worden uitgevoerd. In veel gevallen is het echter flexibeler om aggregatiemicroservices te maken onder het bereik van de API Gateway, dus definieert u de aggregatie in code (dat wil gezegd C#-code):
Zie Het aggregatiepatroon gateway voor meer informatie.
Kruislingse problemen of offloading van gateways. Afhankelijk van de functies die door elk API Gateway-product worden aangeboden, kunt u functionaliteit van afzonderlijke microservices naar de gateway offloaden, waardoor de implementatie van elke microservice wordt vereenvoudigd door kruislingse problemen in één laag samen te voegen. Deze aanpak is vooral handig voor gespecialiseerde functies die complex kunnen zijn om correct te implementeren in elke interne microservice, zoals de volgende functionaliteit:
- Verificatie en autorisatie
- Integratie van servicedetectie
- Antwoordcaching
- Beleid voor opnieuw proberen, circuitonderbreker en QoS
- Snelheidsbeperking en beperking
- Load balancing
- Logboekregistratie, tracering, correlatie
- Headers, queryreeksen en claimtransformatie
- IP-acceptatielijst
Zie het patroon Gateway-offloading voor meer informatie.
Producten gebruiken met API Gateway-functies
Afhankelijk van elke implementatie kunnen er nog veel meer problemen zijn die worden aangeboden door de API Gateways-producten. We verkennen hier:
Azure API Management
Azure API Management (zoals weergegeven in afbeelding 4-14) lost niet alleen uw API Gateway-behoeften op, maar biedt functies zoals het verzamelen van inzichten uit uw API's. Als u een API Management-oplossing gebruikt, is een API Gateway slechts een onderdeel binnen die volledige API Management-oplossing.
Afbeelding 4-14. Azure API Management gebruiken voor uw API Gateway
Azure API Management lost zowel uw API Gateway- als Management-behoeften op, zoals logboekregistratie, beveiliging, meting, enzovoort. Wanneer u een product zoals Azure API Management gebruikt, is het feit dat u mogelijk één API-gateway hebt niet zo riskant omdat dit soort API-gateways 'dunner' zijn, wat betekent dat u geen aangepaste C#-code implementeert die zich kan ontwikkelen naar een monolithisch onderdeel.
De API Gateway-producten fungeren meestal als een omgekeerde proxy voor inkomend verkeer, waar u ook de API's van de interne microservices kunt filteren en autorisatie kunt toepassen op de gepubliceerde API's in deze enkele laag.
De inzichten die beschikbaar zijn in een API Management-systeem, helpen u inzicht te krijgen in hoe uw API's worden gebruikt en hoe ze presteren. Ze doen deze activiteit door u bijna realtime analyserapporten te laten bekijken en trends te identificeren die van invloed kunnen zijn op uw bedrijf. Bovendien kunt u logboeken over aanvraag- en antwoordactiviteit hebben voor verdere online- en offlineanalyse.
Met Azure API Management kunt u uw API's beveiligen met behulp van een sleutel, een token en IP-filtering. Met deze functies kunt u flexibele en verfijnde quota en frequentielimieten afdwingen, de vorm en het gedrag van uw API's wijzigen met behulp van beleid en de prestaties verbeteren met reactiecaching.
In deze handleiding en de referentievoorbeeldtoepassing (eShopOnContainers) is de architectuur beperkt tot een eenvoudigere en aangepaste containerarchitectuur om u te richten op gewone containers zonder PaaS-producten zoals Azure API Management te gebruiken. Maar voor grote microservicetoepassingen die zijn geïmplementeerd in Microsoft Azure, raden we u aan Om Azure API Management te evalueren als basis voor uw API-gateways in productie.
Ocelot
Ocelot is een lichtgewicht API-gateway die wordt aanbevolen voor eenvoudigere benaderingen. Ocelot is een op Open Source .NET Core gebaseerde API-gateway die speciaal is gemaakt voor microservicesarchitecturen die geïntegreerde toegangspunten in hun systemen nodig hebben. Het is lichtgewicht, snel en schaalbaar en biedt routering en verificatie tussen vele andere functies.
De belangrijkste reden om Ocelot te kiezen voor de eShopOnContainers-referentietoepassing 2.0 is omdat Ocelot een .NET Core lightweight API-gateway is die u kunt implementeren in dezelfde toepassingsimplementatieomgeving waar u uw microservices/containers implementeert, zoals een Docker-host, Kubernetes, enzovoort. En omdat het is gebaseerd op .NET Core, is het platformoverschrijdend, zodat u kunt implementeren in Linux of Windows.
De vorige diagrammen met aangepaste API-gateways die in containers worden uitgevoerd, zijn precies hoe u Ocelot ook kunt uitvoeren in een container- en microservicetoepassing.
Daarnaast zijn er veel andere producten in de markt die API Gateways-functies aanbieden, zoals Apigee, Kong, MuleSoft, WSO2 en andere producten zoals Linkerd en Istio voor functies voor binnenkomende toegangscontrollers voor service mesh.
Na de eerste secties over architectuur en patronen wordt in de volgende secties uitgelegd hoe u API-gateways implementeert met Ocelot.
Nadelen van het API Gateway-patroon
Het belangrijkste nadeel is dat wanneer u een API-gateway implementeert, u die laag koppelt aan de interne microservices. Als u deze koppeling gebruikt, kan dit ernstige problemen veroorzaken voor uw toepassing. Clemens Vaster, architect van het Azure Service Bus-team, verwijst naar deze potentiële moeilijkheid als 'de nieuwe ESB' in de sessie 'Messaging and Microservices' op GOTO 2016.
Met behulp van een microservices-API Gateway wordt een extra mogelijk single point of failure gemaakt.
Een API Gateway kan een verhoogde reactietijd veroorzaken vanwege de extra netwerkaanroep. Deze extra aanroep heeft echter meestal minder impact dan het hebben van een clientinterface die te chatty is om de interne microservices rechtstreeks aan te roepen.
Als deze niet goed is uitgeschaald, kan de API-gateway een knelpunt worden.
Voor een API-gateway zijn extra ontwikkelingskosten en toekomstig onderhoud vereist als deze aangepaste logica en gegevensaggregatie bevat. Ontwikkelaars moeten de API-gateway bijwerken om de eindpunten van elke microservice beschikbaar te maken. Bovendien kunnen implementatiewijzigingen in de interne microservices leiden tot codewijzigingen op API Gateway-niveau. Als de API Gateway echter alleen beveiliging, logboekregistratie en versiebeheer toepast (net als bij het gebruik van Azure API Management), zijn deze extra ontwikkelingskosten mogelijk niet van toepassing.
Als de API Gateway is ontwikkeld door één team, kan er sprake zijn van een knelpunt voor ontwikkeling. Dit aspect is een andere reden waarom een betere aanpak is om verschillende fijnmazige API-gateways te hebben die reageren op verschillende clientbehoeften. U kunt de API-gateway ook intern scheiden in meerdere gebieden of lagen die eigendom zijn van de verschillende teams die aan de interne microservices werken.
Aanvullende bronnen
Chris Richardson. Patroon: API-gateway/back-end voor front-end
https://microservices.io/patterns/apigateway.htmlAPI Gateway-patroon
https://learn.microsoft.com/azure/architecture/microservices/gatewayAggregatie- en samenstellingspatroon
https://microservices.io/patterns/data/api-composition.htmlAzure API Management
https://azure.microsoft.com/services/api-management/Udi Dahan. Servicegeoriënteerde samenstelling
https://udidahan.com/2014/07/30/service-oriented-composition-with-video/Clemens Vasters. Berichten en Microservices op GOTO 2016 (video)
https://www.youtube.com/watch?v=rXi5CLjIQ9kAPI-gateway in een Notendop (ASP.NET Core API Gateway Tutorial Series)
https://www.pogsdotnet.com/2018/08/api-gateway-in-nutshell.html