wake-up-neo.com

Wie sollten Microservices mit AWS API Gateway + Lambda/ECS entwickelt werden?

Ich entwickle eine "Micro-Services" -Anwendung unter Verwendung von AWS API Gateway mit Lambda oder ECS für Computing. Das Problem ist nun, dass die Kommunikation zwischen Diensten über API-Aufrufe über das API-Gateway erfolgt. Dies fühlt sich ineffizient und weniger sicher an als es sein kann. Gibt es eine Möglichkeit, meine Microservices performanter und sicherer miteinander zu kommunizieren? Wie irgendwie direkt im privaten Netzwerk sprechen?

Eine Möglichkeit, die ich mir vorgestellt habe, sind mehrere Ebenen des API-Gateways.

  • 1 öffentliches API-Gateway
  • 1 privates API-Gateway pro Microservice. Und jeder Mikrodienst kann einen anderen Mikrodienst "direkt" innerhalb des privaten Netzwerks aufrufen

Aber auf diese Weise muss ich meine Routen in 2 API-Ebenen "duplizieren" ... dies scheint nicht ideal zu sein. Ich dachte, vielleicht {proxy+} verwenden. Also alles, was /payment/{proxy+} ist, geht an das Payment API Gateway und so weiter - es gibt immer noch 2 Ebenen des API Gateways ... aber dies scheint das Beste zu sein, was ich machen kann?

Vielleicht gibt es einen besseren Weg?

7
Jiew Meng

Es gibt viele Möglichkeiten, Mikrodienste aufzubauen. Ich würde mich zunächst mit dem von AWS veröffentlichten Whitepaper vertraut machen: Microservices unter AWS , Whitepaper - PDF version .

In Ihrer Frage stellten Sie fest: "Das Problem ist jetzt die Kommunikation zwischen Diensten über API-Aufrufe über das API-Gateway. Dies fühlt sich ineffizient und weniger sicher an, als es sein kann. Gibt es eine Möglichkeit, meine Mikrodienste miteinander in Kontakt zu bringen.) eine performantere und sicherere Art und Weise? "

Ja - Das AWS Whitepaper und API Gateway FAQ referenzieren das API Gateway als "Eingangstür" zu Ihrer Anwendung. Die Absicht des API-Gateways ist für externe Dienste zu verwenden, die mit Ihren AWS-Diensten kommunizieren. Keine AWS-Dienste, die miteinander kommunizieren.

Es gibt mehrere Möglichkeiten, wie AWS-Ressourcen miteinander kommunizieren können, um Mikrodienste aufzurufen. Einige werden im Whitepaper beschrieben, und dies ist eine weitere Ressource, die ich verwendet habe: Besser zusammen: Amazon ECS und AWS Lambda . Die von Ihnen genutzten Dienste richten sich nach Ihren Anforderungen. 

Durch das Aufteilen monolithischer Anwendungen in kleine Mikrodienste steigt der Kommunikationsaufwand, da Mikrodienste miteinander kommunizieren müssen. In vielen Implementierungen wird REST über HTTP als Kommunikationsprotokoll verwendet. Es ist ein Protokoll mit geringem Gewicht, aber hohe Volumina können Probleme verursachen. In einigen Fällen kann es sinnvoll sein, über die Konsolidierung von Diensten nachzudenken, die viele Nachrichten hin und her senden. Wenn Sie sich in einer Situation befinden, in der Sie mehr und mehr Ihrer Dienste konsolidieren, um die Gesprächsbereitschaft zu reduzieren, sollten Sie Ihre problematischen Domänen und Ihr Domänenmodell überprüfen.

Nach meinem Verständnis besteht die Ursache Ihres Problems darin, Anfragen an Mikrodienste weiterzuleiten. Um die " Eigenschaften von Microservices " beizubehalten, sollten Sie eine einzelne Lösung für das Routing auswählen. 

API-Gateway

Sie haben erwähnt, dass Sie API-Gateway als Routing-Lösung verwenden. API-Gateway kann für das Routing verwendet werden. Wenn Sie sich jedoch für das Routing mit API-Gateway entscheiden, sollten Sie Ihre Routen explizit auf einer Ebene definieren. Warum?

  1. Die Verwendung von {proxy +} erhöht die Angriffsfläche, da Routing in einem anderen Mikrodienst ordnungsgemäß ausgeführt werden muss. 
  2. Das Definieren von Routen in API Gateway hat den Vorteil, dass Ihre API selbstdokumentierend ist. Wenn Sie über mehrere API-Gateways verfügen, werden diese abgeglichen.

Der Nachteil ist, dass dies einige Zeit in Anspruch nimmt und Sie möglicherweise vorhandene APIs ändern müssen, die bereits definiert wurden. Möglicherweise nehmen Sie jedoch bereits Änderungen an der vorhandenen Codebasis vor, um die Best Practices für Mikrodienste zu befolgen.

Lambda oder andere Berechnungsressource

Trotz der oben genannten Gründe für die Verwendung des API-Gateways für das Routing kann eine andere Ressource bei ordnungsgemäßer Konfiguration das Routing ordnungsgemäß verarbeiten. Sie können einen API-Gateway-Proxy für eine Lambda-Funktion einrichten, für die alle Mikrodienstrouten definiert sind, oder eine andere Ressource innerhalb Ihrer VPC mit definierten Routen.

Ergebnis

Was Sie tun, hängt von Ihren Anforderungen und Ihrer Zeit ab. Wenn Sie bereits eine API definiert haben und einfach möchten, dass API Gateway zum Drosseln, Überwachen, Sichern und Protokollieren von Anforderungen verwendet wird, haben Sie API Gateway als Proxy. Wenn Sie das API-Gateway in vollem Umfang nutzen möchten, definieren Sie jede Route explizit darin. Beide Ansätze können den Best Practices für Mikrodienste folgen. Es ist jedoch meine opinion , dass das Definieren jeder öffentlichen API in API Gateway die beste Möglichkeit ist, sich an die Mikrodienstarchitektur anzupassen. Die anderen Antworten sind auch sehr gut geeignet, um die Kompromisse bei jedem Ansatz zu erklären.

3
KiteCoder

Ich gehe zu nehme Lambdas als Lösung an aber es könnten genauso gut ECS-Instanzen oder ELBs sein.

Aktuelles Problem  original problem

Ein wichtiges Konzept, das Sie über Lambdas verstehen müssen, bevor Sie in die Lösung einsteigen, ist die Entkopplung Ihres Anwendungscodes und eines event_source

Eine Ereignisquelle ist eine andere Methode, um Ihr Anwendungscode aufzurufen. Sie haben API-Gateway erwähnt. Dies ist nur eine Methode zum Aufrufen Ihres Lambda (eine HTTP-ANFORDERUNG). Weitere für Ihre Lösung relevante event sources sind:

  • Api-Gateway (Wie bereits erwähnt, nicht für die Kommunikation zwischen Diensten geeignet)
  • Direkter Aufruf (über AWS Sdk, kann synchron oder asynchron sein)
  • SNS (pub/sub, eventbus)
  • Es gibt über 20 verschiedene Arten, ein Lambda aufzurufen. Dokumentation

Anwendungsfall # 1 Sync

Wenn also Ihr HTTP_RESPONSE davon abhängt, ob ein Lambda ein anderes anruft, und von diesem zweiten Lambda-Ergebnis. Eine direkte invoke -Datei ist möglicherweise eine gute Lösung für die Verwendung. Auf diese Weise können Sie invoke das Lambda synchron verwenden. Das bedeutet auch, dass Lambda für ein API-Gateway als Ereignisquelle abonniert werden sollte und über Code zum Normalisieren der zwei verschiedenen Ereignistypen verfügt. (Aus diesem Grund hat die Lambda-Dokumentation normalerweise event als einen der Parameter.)

 Sync use case

Anwendungsfall Nr. 2 Async

Wenn Ihre HTTP-Antwort nicht von der Ausführung der anderen Mikrodienste (Lambdas) abhängt. Ich würde SNS für diesen Anwendungsfall wärmstens empfehlen, da Ihr ursprüngliches Lambda ein einzelnes Ereignis veröffentlicht und Sie mehr als 1 Lambda haben können, das für dieses Ereignis parallel ausgeführt wird.

 Async/parallel execution

Kompliziertere Anwendungsfälle

Für kompliziertere Anwendungsfälle:

4
Dudemullet

Es gibt mehrere Möglichkeiten und Ansätze, um dies zu tun, abgesehen davon, dass Sie an Ihr aktuelles Setup und Ihre Infrastruktur gebunden sind, ohne die Flexibilität zum Implementieren/Ändern der vorhandenen Code-Basis auszuschließen.

Wenn Sie versuchen, zwischen den Diensten hinter dem API-Gateway zu kommunizieren, müssen Sie dies sorgfältig implementieren, um Schleifen zu vermeiden, Ihre Daten offenzulegen oder sogar das Schlimmste zu vermeiden. Blockieren Sie sich selbst. Sehen Sie sich das "generische" Image an, um ein besseres Verständnis zu erhalten:  enter image description here

Bei der Verwendung vonHTTPfür die Kommunikation zwischen den Diensten ist es häufig üblich, dass der Datenverkehr aus der aktuellen Infrastruktur herauskommt und dann durch dasselbe API-Gateway zurückkehrt. Dies kann vermieden werden, indem der andere Dienst direkt ausgeführt wird stattdessen an Ort und Stelle. 

Wenn im vorherigen Bild beispielsweise service B mit service A kommunizieren muss, ist es ratsam, dies über den internen (ELB) -Endpunkt zu tun, anstatt das API-Gateway zu verlassen.

Ein anderer Ansatz ist die Verwendung von "nur"HTTPim API-Gateway und die Verwendung anderer Protokolle für die Kommunikation innerhalb Ihrer Dienste, z. B. gRPC . (In manchen Fällen nicht die beste Alternative, da dies von Ihrer Architektur und der Flexibilität zum Modifizieren/Anpassen von vorhandenem Code abhängig ist.)

Es gibt Fälle, in denen Ihre Infrastruktur komplexer ist und Sie möglicherweise nicht auf Anforderung in Ihren Containern kommunizieren oder die Endpunkte nicht erreichbar sind. In diesem Fall können Sie versuchen, eine ereignisgesteuerte Architektur zu implementieren (SQS und AWS Lambda) )

Ich gehe gerne asynchron durch die Verwendung von Ereignissen/Warteschlangen, wenn möglich, "skaliert" besser aus meiner Sicht und muss der Dienst nur noch Konsumenten/Arbeiter werden. Außerdem muss hier nicht auf eingehende Anfragen gewartet werden (kein HTTP erforderlich) ist ein Artikel, der erklärt, wie man rabbitmq zu diesem Zweck verwendet, um Mikrodienste innerhalb des Dockers zu kommunizieren

Dies sind nur einige Ideen, mit denen Sie hoffen können, Ihren eigenen "besten" Weg zu finden, da sich dies zu sehr unterscheidet und jedes Szenario einzigartig ist.

1
nbari

Ich denke nicht, dass Ihre Frage streng mit AWS zusammenhängt, sondern eher einer allgemeinen Art der Kommunikation zwischen den Diensten.

API-Gateway wird als Edgedienst verwendet, der sich an Ihrer Backend-Grenze befindet und für externe Parteien zugänglich ist. Für die Kommunikation hinter dem API-Gateway zwischen Ihren Mikrodiensten müssen Sie das API-Gateway nicht erneut durchlaufen.

Es gibt zwei Arten der Kommunikation, die ich für Ihren Fall erwähnen würde:

  • HTTP
  • Messaging

HTTP ist die einfachste Art der Kommunikation, da es von Natur aus leichter zu verstehen ist und es eine Unmenge an Bibliotheken gibt, die es einfach zu bedienen machen. 

Trotz der Vorteile gibt es einiges zu beachten.

  • Fehlerbehandlung
  • Stromkreisunterbrechung, falls ein Dienst nicht zur Verfügung steht
  • Konsistenz
  • Wiederholungen
  • Verwenden von Service Discovery (z. B. Eureka), um das System flexibler zu gestalten, wenn Sie einen anderen Service anrufen

Auf der Messaging-Seite müssen Sie sich mit asynchroner Verarbeitung, Infrastrukturproblemen wie dem Einrichten und Verwalten des Message Broker befassen, es ist nicht so einfach wie reines HTTP, aber Sie können Konsistenzprobleme lösen, indem Sie einfach konsistent sind.

Insgesamt gibt es eine Menge Dinge, die Sie beachten müssen, und alles dreht sich um Kompromisse. Wenn Sie gerade erst mit Microservices beginnen, denke ich, ist es am besten, wenn Sie HTTP für die Kommunikation verwenden und dann langsam zur Messaging-Alternative wechseln.

In der Java + Spring Cloud-Netflix-Welt können Sie beispielsweise Eureka mit Feign nutzen. Dadurch ist es sehr einfach, die logische Adresse der Dienste zu verwenden, die von Eureka in tatsächliche IP-Adressen und Ports übersetzt wird. Wenn Sie Swagger für Ihre REST APIs verwenden möchten, können Sie sogar Feign-Client-Stubs daraus generieren.

1
galovics

Ich hatte schon eine Weile die gleiche Frage im Kopf und kann immer noch keine guten generischen Lösungen finden ... Für was es wert ist ...

Wenn die Kommunikation in eine Richtung erfolgt und der "Anrufer" nicht auf ein Ergebnis warten muss, finde ich, dass Kinesis-Streams sehr mächtig sind. Stellen Sie einfach eine "Aufgabe" in den Stream und lassen Sie den Stream einen Lambda auslösen, um ihn zu verarbeiten. Aber das funktioniert natürlich in sehr begrenzten Fällen ...

Für die Antwort-Antwort-Welt rufe ich die API-Gateway-Endpunkte genauso auf, wie ein Endbenutzer dies tun würde (mit zusätzlichem Marshalling und Unmarshaling von Daten, die in die HTTP-Welt passen, und unnötigen mehrfachen Authentifizierungen).

In seltenen Fällen kann es eine einzige Backend-Lambda-Funktion geben, die sowohl vom Gateway-API-Lambda als auch von anderen Microservices direkt aufgerufen wird. Dies fügt einen zusätzlichen "Hop" für "Endbenutzer" hinzu (anstelle von [UI -> Gateway API -> GatewayAPI Lambda], jetzt habe ich [UI -> Gateway API -> GatewayAPI Lambda -> Backend Lambda]), macht jedoch Microservice verursachte Anrufe schneller (da der Anruf und alle zugehörigen Daten nicht mehr durch eine HTTP-Anforderung "getunnelt" werden müssen). Außerdem wird die Architektur dadurch komplizierter (ich habe keine einzige offizielle API mehr, habe aber jetzt eine direkte Abhängigkeit vom "Rückkanal").

0
xpa1492