Das Wissensportal für IT-Professionals. Entdecke die Tiefe und Breite unseres IT-Contents in exklusiven Themenchannels und Magazinmarken.

SIGS DATACOM GmbH

Lindlaustraße 2c, 53842 Troisdorf

Tel: +49 (0)2241/2341-100

kundenservice@sigs-datacom.de

Microservices und die Amazon Cloud

Der Kunde ist König. Das gilt besonders im E-Commerce. Daher ist die Performanz eines Webshops aus Kundensicht wichtig. Können sich Microservices hinsichtlich Deployment, Performanz und Ausfallsicherheit für Online-Shops lohnen? Der Artikel untersucht diese Frage anhand eines Beispiels, das Amazon Cloud verwendet.
Author Image
Jörg Jackisch

Diplom-Informatiker


  • 25.01.2019
  • Lesezeit: 18 Minuten
  • 80 Views

Das Thema Microservices zieht immer mehr Aufmerksamkeit auf sich, auch JavaSPEKTRUM hat ihm schon zahlreiche Artikel gewidmet. Was sich alles hinter diesem Stichwort befindet, soll in diesem Artikel erläutert und dargestellt werden. Ein idealisiertes Beispiel demonstriert, wie eine monolithische Softwareanwendung in eine neue Softwarearchitektur unter Verwendung von Microservices überführt werden kann. Zur infrastrukturellen Bereitstellung der Microservice-Lösung soll die Amazon Cloud genutzt werden.

Welche Vor- und Nachteile diese Transformation bringt und ab wann es ein lohnender Aufwand ist, mit dem Gedanken zu spielen, seine Anwendung in solch eine Architektur zu überführen, wird abschließend in wesentlichen Punkten dargelegt. Dies kann auch Managern, welche gerade dabei sind, eine Analyse zu erstellen, als Entscheidungshilfe dienen.

Transformation vom Monolithen zu einer modularen Architektur

Viele Big Player im E-Commerce sind diesen Schritt schon gegangen. Beispielhafte Namen sind Amazon, eBay oder Netflix. Diese Unternehmen haben ihre Plattformen von einem Monolithen in eine Architektur aus Microservices überführt.

Einer der Hauptgründe für Amazon, in eine Microservice-Architektur zu transformieren, war es, die Services unabhängig voneinander bereitstellen und skalieren zu können. Als die E-Commerce-Plattform noch ein Monolith war, war es sehr schwer, die Anwendung zu skalieren. Bei einer Bereitstellung einer neuen Softwarekomponente mussten immer große Teile der Anwendung neu erstellt und hochgeladen werden. Bei solchen E-Commerce-Riesen spielen schon minimale Zeitverluste bei Prozessen auch monetär eine Rolle. Nach der Umstellung auf die neue Architektur stellen die Entwickler von Amazon alle 12 Sekunden neue Teile und Services bereit.

Auch Zalando hat diese Transformation durchgeführt. Zalando nutzt beispielsweise die Amazon Cloud als Infrastruktur und bildet den Deployment-Prozess mithilfe von AWS (Amazon Webservices) und Docker ab. Die gleiche Herangehensweise wird der Autor auch in diesem Beitrag verfolgen.

Maßgebliche Punkte für Unternehmen, die auf den Umsatz, welcher durch den Handel im Internet erzeugt wird, angewiesen sind, sind:

  • Testbarkeit/Wartbarkeit,
  • Skalierbarkeit,
  • Verfügbarkeit und
  • letztendlich Performanz per User.

Mir ist der letzte Punkt besonders wichtig. Die Performanz der Applikation kann man durch die Skalierung der Hardwarekomponenten erreichen, eine stabile und gleichbleibende Performanz pro User oder Kunde ist im E-Commerce schwieriger zu gewährleisten. Die Performanz pro User wird exponentiell schlechter, je mehr Benutzer die Applikation benutzen. In diesen Fällen muss nicht nur die Applikation selbst skalierbar sein, sondern auch die Infrastrukturkomponenten, wie zum Beispiel die Load-Balancer.

Alle genannten Punkte werden durch die Modularität, welche diese Architektur mit sich bringt, unterstützt und durch die neue Herangehensweise erreicht. Die Einführung bringt nicht nur technische und infrastrukturelle Veränderungen mit sich, sondern auch organisatorische. Auf all die Schwierigkeiten bei der Transformation geht der Artikel ein.

Überblick über die Microservice-Architektur

Hinter dem Wort Microservices verbirgt sich mehr als eine Architekturmethode, es ist eine Philosophie, welche auf allen Ebenen der Organisation zu einer Veränderung führen sollte und gelebt werden muss.

Definition einer Microservice-Architektur
Eine Microservice-Architektur stellt ein Muster in der Softwareentwicklung dar, bei welchem die Kernanwendung eine Komposition von unterschiedlichen, eigenständigen Services ist. Dabei wird der hauptsächliche Fokus der Architektur auf die Funktionalität gelegt. Die Kommunikation der Services untereinander findet jeweils durch eine öffentlich beschriebene Schnittstelle statt. Dadurch entsteht eine lose Kopplung der Services.

Die Kommunikation im Allgemeinen kann dabei unterschiedliche Protokolle nutzen, beispielsweise REST per http(s), JSON oder auch über Messages. Innerhalb der Microservices können unterschiedliche Programmiersprachen benutzt werden, jeweils diejenige, welche für den bestimmten Service effektiv geeignet ist.

Dies führt dazu, dass kein fester Technologie-Stack für einen Service festgelegt ist. Ein Microservice muss selbstständig lauffähig und dadurch auch testbar sein und er sollte dediziert hostbar sein. Dies bildet die Grundlage der Skalierbarkeit, sowohl vertikal als auch horizontal.

Wie groß sollte ein Microservice sein?
Wie schon der Name sagt, sollte der Service mikro sein, also sehr klein. Dennoch bleibt dabei die Frage offen, wie groß ist mikro. Da per Definition für eine Microservice-Architektur kein Technologie-Stack vorgegeben wird, hängt die Größe natürlich von der jeweils gewählten Programmiersprache ab. Als messbare Einheit innerhalb der Programmierung wurden die sogenannten LoC eingeführt, LoC steht für Lines of Code und sollen eine Komplexität allgemein beschreiben. Bei der Anwendung dieser Metrik ist darauf zu achten, dass Microservices ein Architekturmuster ist, welches abhängig von der fachlichen Domäne ist.

Dennoch ist sehr gut definierbar, wie groß ein Microservice sein sollte. Dabei hilft der Ansatz aus der Unix-Philosophie, welcher genau dies beschreibt. Im Buch „The Art of Unix Programming“, welches 2003 von Eric Reymond publiziert wurde, werden 17 Regeln beschrieben. Eine dieser Regeln ist die der Modularität. Diese besagt, dass ein Programm unter Unix, anwendbar auf die Services hier, genau eine einzige Aufgabe lösen und über definierte Interfaces kommunizieren soll. „Do One Thing and Do It Well“ ist das Statement, was genau dies beschreibt.

Ein weiteres Prinzip, an welches man sich bei der Entwicklung solcher Services halten kann, ist das „KISS“, welches für Keep it Simple, Stupid steht.

Ein weiteres Merkmal für die Größe eines Microservice stellt die Größe des Teams dar, welches ihn entwickelt. Ein Microservice sollte nur von einem Team entwickelt werden.

Nanoservices
Die Ersten sprechen nun davon, noch kleiner zu werden als Microservices. Ein Microservice kann von kleinen Teams entwickelt werden und ist unabhängig von anderen Komponenten, dennoch bildet er selbst einen Deployment-Monolithen. Bei dem Ansatz der Microservice-Architekturen wird nämlich vorgeschlagen, dass jeder Service seinen eigenen Deployment-Container hat. Meistens wird dies mit Docker oder einer anderen Container-Virtualisierung realisiert. Dies führt nun dazu, dass jeder Microservice sein eigenes Dateisystem und die eigene Umgebung hat. Man versucht bei der Entwicklung, den Programmcode zwar so gering wie nur möglich zu halten, aber jeweils pro Service stellt man ein eigenes Dateisystem zur Verfügung.

Der Ansatz bei Nanoservices will nun die Services so klein halten, dass auch in der Virtualisierung die benutzten Artefakte so klein wie nur möglich werden.

Gesetz von Conway
Das Gesetz von Conway beschreibt, dass die Kommunikation der Softwarekomponenten abhängig ist von der Kommunikation im Entwicklerteam:

Organizations which design systems […] are constrained to produce designs which are copies of the communication structures of these organizations.” Die Qualität der Microservices und der veröffentlichten Schnittstellen hängt also davon ab, wie stark die Organisation und die Kommunikation im Team sind. Die Kommunikationsstrukturen, welche Conway meint, müssen nicht dem Organigramm oder einer Unternehmensstruktur entsprechen, oft gibt es informelle Kommunikationsstrukturen, welche innerhalb dieses Kontextes betrachtet werden können.

Der Grund, warum Conways Gesetz bei der Betrachtung von Microservices eine Rolle spielt, liegt auf der Hand: Angenommen, zwei Teams erstellen isoliert voneinander zwei unterschiedliche Microservices. Diese beiden Microservices kommunizieren über eine Schnittstelle miteinander. Vorher müssen allerdings die beiden Teams miteinander kommunizieren, um alle Anforderungen für die Schnittstelle zu definieren. Daraus entstehen der Vor- und Nachteil der Architektur im organisatorischen Sinne, letztendlich ist es einfacher, mit einem Kollegen im gleichen Raum zusammenzuarbeiten als eventuell auf einem anderen Kontinent mit anderer Zeitzone.

Vorteile der Microservice-Architektur
Sobald man von Microservice-Architekturen liest oder mit anderen Kollegen darüber spricht, werden oft die gleichen Vorteile genannt. Die Vorteile, welche diese Architektur mitbringt, sind allerdings nichts Neues, sondern bilden die Vorteile der Modularität von Softwarepaketen ab:

  • Leichte Testbarkeit, da man nur diesen einen Service, diese eine Aufgabe testen muss und nicht ein komplexes System.
  • Leichte Integrationstests: Man testet lediglich die Schnittstellen zum Service hin.
  • Leichte Wartbarkeit/Erweiterbarkeit: Da per Definition der Service so klein sein soll, dass ihn ein Entwickler sehr einfach und schnell verstehen kann, sind die Entwickler im Allgemeinen sehr tief im Detail des Service.
  • Unabhängiges Deployment: Ein Microservice kann in Produktion gebracht werden, ohne dass die anderen deployt oder verändert werden müssen.
  • In der Regel laufen die einzelnen Services innerhalb einer Container-Virtualisierung. Als Vorteil der Container-Virtualisierung und der Modularität kann man die Services skalieren, wenn man mehr oder weniger Ressourcen benötigt. Letztendlich sind für die Skalierbarkeit nur ein Load-Balancer und mehrere Instanzen der virtualisierten Container notwendig.
  • Die Robustheit der gesamten Software, wenn die anderen Services einen Ausfall von einem Service tolerieren. Falls beispielsweise ein Microservice zu viel Speicher alloziert oder die CPU zu stark belastet, geschieht das nur innerhalb des einzelnen Prozesses und hat normalerweise keinen Einfluss auf die anderen Services.

Nachteile der Microservice-Architektur
Da dieses Konzept so viele erfreuliche Vorteile hat, sind die Nachteile umso interessanter. Diese sollten, bevor man mit dem Projekt der Transformation beginnt, berücksichtigt werden:

  • Hohe Latenzzeiten: Die Kommunikation zwischen den Services erfolgt wie in einem verteilten System, jeder Service besitzt seine eigene virtuelle Maschine, mit einem eigenen Dateisystem und eigenem Betriebssystem. Dadurch erfolgt die Kommunikation über das Netzwerk. Diese Kommunikation ist selbstverständlich viel langsamer als zwischen Prozessen innerhalb einer Maschine oder innerhalb eines Applikationsservers.
  • Die große Unabhängigkeit der Microservices: Dies bringt zwar viele Vorteile, ist gleichzeitig aber auch ein großer Nachteil, denn dies führt dazu, dass der Programmcode nahezu nicht mehr wiederverwendbar wird. Die Teams arbeiten isoliert voneinander und setzen eventuell sogar andere Programmiersprachen ein. So ist Programmcode zwischen Teams nur schwer wieder zu verwenden.
  • Einen weiteren Nachteil bringt die monolithische Struktur innerhalb von Microservices. Jeder Microservice ist letztendlich ein Deployment-Monolith, was dazu führt, dass man für den Deployment-Prozess der einzelnen Services wieder separate Infrastruktur benötigt. Diese muss verwaltet werden, was schlussendlich Kosten erzeugt.

Microservice-Architektur in der Cloud

Mittlerweile bieten viele großen Unternehmen die Möglichkeit an, Cloud-Services bei ihnen zu nutzen. Alle haben unterschiedliche Konzepte und Schnittstellen. Die führenden Anbieter sind Microsoft mit Azure, Google mit der Google Cloud Platform und Amazon mit Amazon EC2. Dieser Dienst nennt sich Amazon Elastic Compute Cloud, die 2 steht dabei nicht für die Version 2, sondern für zweimal das C (Compute Cloud).

Amazone EC2
Der Webservice Amazon Elastic Cloud Compute stellt sichere, skalierbare Rechenkapazität in der Cloud bereit. Der Service ist darauf ausgelegt, die Entwicklung in der Cloud zu erleichtern. Dies ist der einführende Satz, mit welchem Amazon seinen Cloud-Dienst anbietet und bewirbt.

Nun stellt sich natürlich die Frage, was dies praktisch bedeutet. Wie bei den Nachteilen festgestellt, benötigt ein Microservice für das Deployment eine eigene Infrastruktur, da jeder Microservice eigenständig ist. Für das Deployment einzelner Funktionen, welche in JavaScript, Java oder Python geschrieben sind, bietet Amazon mit seinem Dienst Amazon Lambda eine Möglichkeit, diese einfach per Konsole zu deployen. Eine solche Technologie verringert den Aufwand für das Deployment eines Microservice erheblich, es muss nur ein Werkzeug per CMD benutzt werden und den Rest erledigt die Infrastruktur. Dabei ist nicht mal mehr ein Aufbau eines Docker-Containers oder Ähnlichem notwendig.

Den Service von Amazon kann man kostenlos testen, andernfalls erfolgt die Abrechnung pro Ressource und pro Nutzung der Ressource.

Getting Started
Nach dem Login bei Amazons AWS kann man links oben auf den Reiter der Services klicken und bekommt einen Überblick, was Amazon alles mit seinen Cloud-Diensten abdeckt. Abbildung 1 stellt dies dar, im rot markierten Teil befindet sich der Bereich von Amazon für die Cloud-Dienste, welche für Microservices benötigt werden.

Abb. 1: Amazon Cloud Services

Abb. 2: Architektur der beiden unterschiedlichen Herangehensweisen

Es gibt zwei unterschiedliche Herangehensweisen (s. Abb. 2). Im ersten Schritt navigiert man dabei zu EC2. Eine Infrastruktur, welche für einen Microservice geeignet ist, besteht aus vier Ebenen:

  • der Ebenen, welche für die Auslieferung des Contents verantwortlich ist,
  • der sogenannten API-Schicht, welche die Schnittstelle des Microservices darstellt,
  • der Application-Schicht und
  • der Persistence-Schicht.

In der Application-Schicht befindet sich ein Elastic Load Balancer und ein EC2, in der Persistence-Schicht ein Elastic Cache und ein RDS, welches ein Datenbanksystem innerhalb der Cloud darstellt.

Die API-Schicht ist ähnlich der Application-Schicht, in welcher sich ein EC2 befindet und wieder ein Load-Balancer. Im sogenannten Content Delivery befinden sich die Cloud-Front und ein Amazon S3 Bucket, über welchen der statische Content innerhalb eines CDNs ausgeliefert wird.

Um nun den Deployment-Prozess zu vereinfachen und keine EC2, welche die Container repräsentieren, zu nutzen, kann man stattdessen innerhalb der Applikationsschicht ein Lambda nutzen. Dieses übernimmt das komplette Management, von der Skalierung bis hin zum Deployment. Für die API-Schicht steht ein sogenanntes API-Gateway und für die Persistence-Schicht eine Dynamio DB zur Verfügung. Diese zweite Herangehensweise führt zu einer Komplexitätsreduktion.

Die Komponenten selbst kann man im Backend von Amazon AWS konfigurieren. Der Autor empfiehlt hier die Variante des Managements zu verwenden, diese ist wesentlich einfacher und Lambda ist in den API Gateways direkt integriert, sodass es die komplette Verteilung und Kapazitätsbereitstellung übernimmt. Die Integration mithilfe von Lambda ist eine sogenannte Serverless Integration, dies ist natürlich nicht bei allen Anwendungsfällen möglich.

Listing 1 zeigt die JSON-Datei, welche benötigt wird, um einen Container für die Microservices bereitzustellen. Dies kann man selbstverständlich auch in der AWS Console machen, aber durch die Automatisierung mithilfe von JSON ist dies viel schneller.

{
"containerDefinitions": [{
 "name": "[service-name]",
 "image":
 "[account-id].dkr.ecr.us-west-2.amazonaws.com/[service-name]:[tag]",
 "memoryReservation": "256",
 "cpu": "256",
 "essential": true,
 "portMappings": [{
 "hostPort": "0",
 "containerPort": "3000",
 "protocol": "tcp"
 } ]
}],
"volumes": [],
"networkMode": "bridge",
"placementConstraints": [],
"family": "[service-name]"
}
Listing 1: JSON-Datei zur Bereitstellung eines Containers für die Microservices

Amazon bietet dabei nicht nur die Bereitstellung der Services, sondern auch das komplette Monitoring. Zusätzlich bietet Amazon hier auch ein komplettes Set von Reports hinsichtlich Ressourcen-Verbrauch und Last-Verteilung der einzelnen Services.

Das Szenario E-Commerce

In diesem Szenario soll verdeutlicht werden, wie ein Betreiber einer E-Commerce-Plattform an das Thema Microservices in der Cloud herangehen kann. Wie analysiert man die bestimmten Services und wie ist die Vorgehensweise, um nach dem Prinzip „teile und herrsche“ (Devide and Conquer) die Plattform Stück für Stück in Microservices zu transformieren. Am Ende steht das große Ziel, eine Landschaft von unterschiedlichen Services zu haben, welche dann in einer Makro-Struktur den Online-Shop wieder abbilden.

Amazon AWS empfiehlt bei der Transformation vom Monolithen hin zu einer modularen Architektur, dass man als Vorbereitung den Monolithen auch innerhalb der AWS-Infrastruktur hostet. Dies bringt den Vorteil, dass man mithilfe der Load-Balancer im Backend von Amazon den Switch zwischen neuer und alter Architektur vornehmen kann.

Die Services eines Webshops
Eine E-Commerce-Plattform besteht im Allgemeinen aus vielen unterschiedlichen Services. Um herauszufinden, welche Services es gibt und welche man mithilfe von Microservices extrahieren kann, geht man hier nach dem Prinzip „teile und herrsche“ vor.

Abbildung 3 soll diese Vorgehensweise verdeutlichen. Als oberste Ebene analysiert man, wie man ganz grob die E-Commerce-Plattform zerteilen kann. Man findet die drei Bereiche Präsentation der Produkte, Bereich des Kunden und Verkaufsabwicklung. Diese obersten Bereiche untergliedern sich nun erneut.

Die Präsentation kann man in sogenannte Einkaufswelten unterteilen, diese stellen die Startseite dar, gewisse Landingpages und Marketing-Seiten zum Bewerben der Produkte, den Produktkatalog, die Produktdetail- und Service-Seiten, beispielsweise AGBs, das Impressum, welche Zahlungsmodalitäten der Webshop anbietet.

Diese drei Bereiche können wiederum von einzelnen Teams erstellt und erzeugt werden, hier kommen sogar interdisziplinäre Teams zum Einsatz. Innerhalb des Bereiches der Produktdetailseiten sollte sich eine Person mit Kenntnissen im Bereich SEO befinden, wiederum im Bereich der Einkaufswelten eine Person mit Marketing-Fähigkeiten. Den Bereich der Produktdetailseiten kann man jetzt wiederum in einzelne Services unterteilen, wie Darstellung, Zubehör, Up- und Crossselling.

Der Bereich des Kunden stellt dessen Anmeldung an der E-Commerce-Plattform dar. Dort kann der Kunde seine Adressen verwalten, seine schon getätigten Bestellungen einsehen, sein Passwort ändern.

Letztendlich der wichtigste Bereich eines Betreibers solch einer Plattform ist die komplette Verkaufsabwicklung. Vom Warenkorb über den Checkout bis hin zur Zahlungsabwicklung. Der Kunde kann hier auch wählen, ob er eventuell einen Express-Versand wünscht.

Bei der Zerlegung des Monolithen fällt nun bereits der erste Nachteil auf: die Wiederverwendbarkeit. Im Bereich des Kunden werden Bestellungen benötigt, um dem Kunden seine bisher getätigten Bestellungen anzuzeigen, aber eine Bestellung kann auch im Service zur Abwicklung existieren. In der Architektur unseres Monolithen würden wir eine Klasse Order erstellen, welche die jeweiligen Methoden bereitstellt. Da wir hier aber unsere Services nach Fachlichkeit abstrahieren, wird es die Order-Klasse in unterschiedlichen Services mit unterschiedlicher Implementierung immer wieder geben.

Sobald man den Entwurf der Zerlegung des Monolithen in die gedachten Services fertiggestellt hat, sollte man ein Servicediagramm erstellen und dort den Entwurf erstellen, wie und welche Services miteinander kommunizieren. Als Beispiel kann man wieder den Amazon Webshop betrachten, dort kann man innerhalb der Produktdetailseite einen Express-Checkout nutzen. Dies zeigt deutlich, dass viele unterschiedliche Services miteinander sprechen müssen. Das wirkt sich wieder auf die Last der Performanz der gesamten Applikation, schlussendlich aber auf die Performanz pro User aus.

Nachdem die Kommunikation der Services und die Services selbst definiert wurden, kann man beginnen, einzelne Services neu zu entwickeln und aus dem Monolithen herauszulösen. Dies macht man nun Service für Service. Man hat durch die Load-Balancer, welche sich innerhalb jeder Schicht befinden, die Möglichkeit, die Services jederzeit mit einem sogenannten Zero-Downtime-Deployment zur Verfügung zu stellen. Es werden keine Veränderungen mehr im DNS benötigt, dies kann man alles innerhalb seiner Cloud-Infrastruktur konfigurieren.

Abb. 3: Zerlegung in die einzelnen Services

Lohnt sich der Aufwand?

Im Artikel wurden die Vorteile von Microservices beschrieben. Nach unterschiedlichen Analysen, vom Requirement bis hin zur Machbarkeit anhand der verfügbaren Ressourcen, stellt sich dem Softwarebetreiber oder vielmehr dem Webshop-Betreiber die Frage, ob man diese Transformation seines Shops machen soll oder nicht.

Nach der Erfahrung des Autors hängt dies natürlich von unterschiedlichen Parametern ab. Diese Parameter sind dabei nicht nur Zielparameter, anhand welcher man die KPIs seiner Plattform messen kann, wie Performanz, Erweiterbarkeit, Wartbarkeit, sondern auch organisatorische Parameter.

Wichtig ist bei der Planung und der daraus entstehenden Machbarkeitsanalyse die Definition of Done. Die Microservice-Architektur muss anschließend im Kontext der Realisierbarkeit der qualitativen Ziele erforscht werden. Anhand des Beispiels einer E-Commerce-Plattform ist bei der Zerlegung der Services schon aufgefallen, dass man ein relativ großes Team, welches im Idealfall interdisziplinär zusammengestellt ist, benötigt.

Wenn man nun von einer Neuentwicklung spricht, kann man sich die Ressourcen soweit bereitstellen, wie man diese benötigt. Ist man allerdings selbst der Betreiber einer solchen Plattform und plant eine Transformation vom Monolithen hin zu einer modularen Struktur mithilfe dieser Architektur, sollte man sehr genau prüfen, ob alle Ressourcen zur Verfügung stehen und wie die bestehende Plattform während der Transformation weiterentwickelt wird. Des Weiteren empfiehlt es sich, eine Transformation der organisatorischen Struktur hin zu der Fachlichkeit der Services vorzunehmen. Hier ist es empfehlenswert, die Plattform teilweise als Monolith weiterlaufen zu lassen und Service für Service herauszulösen.

. . .

Author Image

Jörg Jackisch

Diplom-Informatiker
Zu Inhalten

ist Diplom-Informatiker. Er stammt aus Chemnitz und wohnt und arbeitet heute im Süden Münchens. Seit mehr als zehn Jahren ist Jörg Jackisch im Bereich der Softwareentwicklung tätig. Er beschäftigt sich hauptsächlich mit dem Design und der Entwicklung komplexer Architekturen von Webanwendungen.


Artikel teilen