Von Spring Boot nach AWS Lambda.

In diesem Eintrag möchte ich die Migration eines bestehenden Microservice nach AWS Lambda beschreiben. Ich beginne also mit einer kurzen Wiederholung meines Beispiels aus der Artikelserie „Resilient Microservices“ aus dem Javamagazin.

axx2cld-microservice-setup

Bei dieser Demo handelt es sich um vier Microservices:

  • Main: Zeigt die Landingpage an und bietet die Möglichkeit weiter zu verzweigen zu Content, Login oder Registration
  • Content: Zeigt den eigentlichen Inhalt an. Abhängig vom Login und der damit verbundenen Rolle hat der Benutzer mehr oder weniger Möglichkeiten.
  • Login: Hier kann sich der Benutzer einloggen.
  • Registration: Hier kann sich der Nutzer registrieren und anschließend einloggen.

Bei dieser Demo habe ich eine besondere Form der Verfügbarkeit eingeführt, indem ich Daten je Microservice gezielt redundant gehalten habe. Bei Ausfall eines Microservice wie z.B. der Registrierung, funktioniert das Login weiterhin, da es sich die notwendigen Daten des Nutzers (Account, Passwort) zuvor per Polling von der Registrierung gelesen und lokal abgespeichert hat.

Die Implementierung erfolgte in jQuery Mobile und Spring Boot. Für die Persistenz habe ich Apache Derby genutzt. Hier habe ich zum einen die Registrierungsdaten (persistent) abgelegt sowie die Logindaten (in memory) zu Redundanzzwecken kopiert. Des Weiteren habe ich die Metadaten für den Content in einer NoSQL DB abgelegt, hier also Mongo DB. Hier nun der Migrationspfad bottom up.

Persistenz

Amazon bietet diverse Lösungen zum Speichern von Daten an. In meinem Fall benötige ich eine relationale Datenbank sowie eine NoSQL DB.

Bei den relationalen Datenbanken hat man die Wahl zwischen Amazon „Aurora“ sowie Amazon „Relational Database Service“ (RDS). „Aurora“ ist mehr ein Service als nur eine Datenbank. Sie ist MySQL-kompatibel, skaliert gut, ist performant und sehr gut abgesichert. Das wirklich ideale ist, dass man sich bis zu einem gewissen Grade nicht drum kümmern muss, dafür fallen Bereitstellungsgebühren an.

Das ist bei Amazon RDS anders. Hier kann man im Grunde relativ fix eine Datenbank (PostgreSQL, MySQL, MariaDB, Oracle und Microsoft SQL Server.) in der Cloud einrichten, ist für deren Sizing und Betrieb selbst verantwortlich. Je nach Größe ist diese dann auch kostenlos. Für meine Migration hier werde ich eine MySQL DB nutzen. Somit besteht die Option, diese später nach Aurora zu portieren.

Eine erste Änderung gegenüber der vorigen Lösung gibt es jedoch schon. Ich werde keine zwei Instanzen getrennt hochziehen. Amazon bietet mir relativ einfach die Möglichkeit an, die DB hochverfügbar auszulegen.

Für das Speichern der Daten je Microservice verwende ich daher jeweils ein eigenes Schema, um die Daten so weiterhin sauber zu trennen und den Bounded Context aufrecht zu erhalten.

schemasetup

 

Das Speichern der Metadaten des Content Microservice erfolgt in der Amazon eigenen NoSQL Datenbank „DynamoDB“.

Logik

Als nächstes muss nun die eigentliche Logik implementiert werden. Hier finden die größten Änderungen statt und ich werde wohl nur wenig Code übernehmen können. Die einzelnen Methoden des CRUD Interface je Microservice werde ich als „Lambdas“ implementieren. Allerdings geht dies nur in Zusammenspiel mit dem „API Gateway“. Während in den Lambdas die eigentliche Funktionalität liegt werden diese über das „API Gateway“ mittels REST Protokoll angesprochen.

Hier gibt es dann auch schon die erste Herausforderung. Alle Beispiele, die ich bisher gefunden habe, sprechen eine Lambdafunktion über eine URL an. Unter REST ist es aber nun mal so, dass auf eine URL die vier http Methoden GET, PUT, POST und DELTE entsprechende den CRUD Anforderungen unserer Microservices, abgebildet werden müssen. Hierzu bietet das „API Gateway“ vier Möglichkeiten auf die jeweilige URL konfigurativ einzuwirken. Das genaue Vorgehen beschreibe ich später, entscheidend ist jedoch, dass ich ein CRUD Interface auf eine Lambda Methode abbilden möchte und nicht auf vier.

Was die zu verwendenden Frameworks betrifft gilt es ja nun entsprechenden Ersatz für Spring zu finden. Viele Dinge werden bereits durch das Amazon SDK sowie Runtime für Lambda erledigt. Somit muss man sich z.B. nicht mehr um das Mapping von JSON auf ein Pojo kümmern. Auch Security wird durch Amazon abgedeckt, hierzu gleich mehr. Somit muss man sich eigentlich nur noch um die eigentliche Geschäftslogik sowie Persistenz kümmern. Aus diesem Grund werde ich auf Hibernate sowie Apache Commons zurückgreifen. Ziel ist es, die eigentlichen Lambdas so klein wie möglich zu  halten und hierzu ggf. auch etwas mehr Code zu riskieren.

Präsentation

Bei der Präsentation wird es wiederum angenehm. Ich denke, dass ich große Teile der Anwendung einfach übernehmen kann. Statt diese aber auf einem dedizierten WebServer  in der Cloud zu hosten wird diese über Amazon „Simple Storage Service“ (kurz Amazon S3) ausgeliefert. Die dazugehörige URL wird in Amazon „Route 53“ eingerichtet. Der eigentliche Content, in meinem Fall also eine größere Anzahl von Bildern, wird über das Amazon eigene CDN „CloudFront“ bereitgestellt.

Bei der eigentlichen WebAnwendung handelt es sich um einen mobilen HTML5 Client, der mittels REST mit dem Backend des jeweils dazugehörigen Microservices spricht. Hierbei tritt ein angenehmer Nebeneffekt auf. Da die REST-Schnittstelle via „API Gateway“ zur Verfügung gestellt wird tritt nun das Problem mit der Verletzung der Same-Origin-Policy nicht mehr auf. Bei der bisherigen Lösung liefen die Microservices jeweils unter einem eigenen Port. Dies musste ich in Spring Boot berücksichtigen und entsprechende Ausnahmen konfigurieren.

Authentisierung und Autorisierung

In der bestehenden Microservice Lösung basierte dieser Aspekt auf einem selbst implementierten OAuth2 Microservice. Hierzu hatte ich im Login Microservice eine Tokengenerierung, -verwaltung sowie –validierung implementiert. Aber auch hier hat Amazon eine Lösung parat und diese lautet IAM (Identity and Access Management). Allerdings bietet Amazon hier keine komplette Out-of-the-Box Lösung an. IAM dient mehr der Verwaltung von technischen Usern. Das kann man auch daran erkennen, dass man je IAM-Account nur maximal 5.000 Benutzer anlegen kann, für die meisten WebSites zu wenig. Amazon bietet aber innerhalb von IAM einen weiteren Service an, AWS Security Token Service (AWS STS). Dieser stellt Token mit einem begrenzten Gültigkeitszeitraum aus. Diese Token können dann genutzt werden, um auf die eigentliche Lambda Funktionen zugreifen zu können. Lediglich die Benutzerverwaltung muss dann noch selbst geschrieben werden.

Zielarchitektur

Das folgende Diagramm zeigt nun die angestrebte Zielarchitektur unter Verwendung aller AWS Dienste:

zielarchitektur

Autor: Oliver Wronka

Oliver Wronka befasst sich mit Java seit der Version 1.0. Schwerpunkt sind javabasierte Backendsysteme in seiner Funktion als Principal Softwarearchitekt bei der axxessio GmbH mit Sitz in Bonn.