Performance-Falle: Microservice

Latenzen im Netzwerk gefährden die Performance

Übermäßig viele Microservice-Aufrufe - Software Performance Anti-Pattern von Nikolai Moesus | QMETHODS | August 2017
 

Anti-Pattern Beschreibung

Microservices sind ein modernes Architekturmuster in dem eine komplexe Anwendung aus vielen kleinen Komponenten besteht. Zahlreiche bekannte Internetanwendungen verwenden Microservices im Hintergrund, darunter z.B. Google, Amazon, Twitter und Netflix. Allerdings haben Microservices natürlich nicht nur Vorteile und bei ungeschickter Umsetzung kann ein ganz bestimmter Nachteil stark in den Vordergrund treten: Netzwerk-Latenzen.
Wenn die Microservices auf unterschiedliche Server verteilt sind, was aus verschiedenen Gründen häufig der Fall ist, fällt pro Aufruf eines Microservices einmal die Netzwerk-Latenz an. Besteht nun die Architektur aus vielen Microservices, die miteinander kommunizieren müssen, können sich Latenzen schnell aufsummieren und die Gesamtperformance signifikant verschlechtern.
Um die ungefähre Größenordnung der Latenzen zeigen zu können, haben wir einige Benchmarks durchgeführt. Wir verwenden dafür wieder unser Performance-Servlet, das sowohl die Benchmarks durchführt, sowie auch als Microservice fungiert. Der unten stehende Quelltext ist der Ausschnitt im Performance-Servlet, der sich um das beantworten der Benchmark-Anfrage kümmert. Es wird die aktuelle Zeit zurückgegeben.
if (request.getParameter("microcall") != null) {
	printWriter.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
	return;
}
Um eine gute Übersicht zu erhalten, wie sehr die Latenz von der verwendeteden Netzwerkarchitektur abhängt, vergleichen wir 4 unterschiedliche Fälle:
  • Aufruf einer Funktion: In einer monolithischen Anwendung gibt es keine Microservices. 
  • Aufruf über REST-Schnittstelle eines Microservice der im selben Tomcat läuft. 
  • Microservice der in einem anderen Tomcat läuft aber auf dem selben Host. 
  • Microservice der auf einem anderen Host läuft, beide Rechner im LAN. 
 

Analyse der Laufzeit

Zur Durchführung der Benchmarks wurden die folgenden Einstellungen verwendet. Die Zahl der Durchläufe muss relativ klein gehalten werden, da sonst die Laufzeit der einzelnen Benchmarks zu groß wird. Das Warm-Up muss aus dem gleichen Grund ausgelassen werden.
  • 1000 Durchläufe 
  • kein Warm-Up 
  • keine explizite Garbage Collection vor dem Start 
Es ist deutlich erkennbar, dass sich die Ausführungszeiten über mehrere Größenordnungen erstrecken. Eine wichtige Erkenntnis ist, dass die Ausführung als REST-Microservice auf einem Computer, also ohne die Verwendung des Netzwerks, schon 60 - 70 mal länger dauert als ein Funktionsaufruf innerhalb eines Programms. Bei Nutzung des Netzwerkes steigt die Ausführungszeit erneut deutlich an.
 
Übermäßig viele Microservice-Aufrufe - Software Performance Anti-Pattern
Abbildung: Veranschaulichung der Kosten von Microservice-Aufrufen
 
Um zusätzlich die Auswirkungen der Netzwerkqualität zu ermitteln, haben wir das Benchmark noch erweitert um zwei weiteren Varianten. In der ersten wird einer der beteiligten Computer nur über WLAN angesprochen, in der zweiten dann beide. Es wir deutlich, dass die Ausführungszeit des Benchmarks stark abhängig ist von der verwendeten Netzwerktechnologie. In unserem Versuchsaufbau ist offenbar die Latenz des WLAN so groß, dass die Ausführungszeit noch 10 mal länger ist als bei einer LAN-Verbindung.
 
Übermäßig viele Microservice-Aufrufe - Software Performance Anti-Pattern
Abbildung: Zusätzliche Kosten durch Netzwerklatenz
 
Der Softwarecode für das Java Performance Servlet zur Vermessung der Implementierungsvarianten steht im QMETHODS GitHub zur Verfügung. Nutzen sie es, um Experimente in ihrer eigenen Umgebung auszuführen.
QMETHODS Github
 

Refactoring Empfehlung

Es sollte überprüft werden, ob für die zu bewältigenden Aufgaben die Microservice-Architektur ein angemessener Ansatz ist, insbesondere in Hinblick auf die durch Latenzen entstehenden Schwierigkeiten. Eine weitere Abwägung ist, wie klein die Microservices gestaltet werden sollten. Ein Microservice wie in unserem Beispiel, der nicht mehr macht als die aktuelle Uhrzeit in einen String zu formatieren, wird wohl in den wenigsten Fällen angemessen sein.
Außerdem ist bei der Architekturentscheidung bereits zu berücksichtigen, wie hoch die Latenzen in der vorgesehenen Umgebung sind, um Abschätzungen für die spätere Antwortzeit der Anwendung machen zu können. Sollte ein Performance-Problem dadurch frühzeitig erkannt werden, ist es jetzt noch möglich, die Architektur entsprechend anzupassen oder höhere Ansprüche an die Laufzeitumgebung zu stellen.
 
Zurück zur Anti-Pattern Übersichtseite



Ihr Kommentar zum Blog-Beitrag

Nennen Sie uns bitte Ihren Namen und E-Mail-Adresse zur Verifikation. Die E-Mail Adresse wird nicht veröffentlicht!