Microservices, Widerstandsfähigkeit

Widerstandfähigkeit eines Microservices Systems in Bezug auf Serviceausfälle oder Netzwerklatenz war ein wichtiger Aspekt, welchen wir in unserem Microservices Projekt eingehend untersuchen wollten. Daher freue ich mich dieses Thema und unsere Erfahrungen in unserer Blogserie etwas eingehender beleuchten zu können.

Widerstandsfähig bezieht sich hierbei auf die Client Anwendung, welche die einzelnen nachgelagerten Microservices verwendet. Dieser Begriff meint dabei, dass die Client Anwendung auch im Fall von Netzwerk- bzw. Serviceausfällen nicht blockiert und immer noch durch den Anwender verwendet werden kann. Blockieren kann die Anwendung zum Beispiel, wenn diese einen Microservice verwendet, welcher sehr viel Zeit benötigt, um eine Antwort im Netzwerk bereit zu stellen. Warum dieser Microservice nicht schnell genug antwortet, spielt bei dieser Betrachtung keine Rolle. Die Client Anwendung wartet solange bis entweder die Antwort eintrifft oder aber ein zuvor definierter Timeout einen Fehler erzeugt. Eine hohe Wartezeit einer Anfrage kann bei starker Verwendung der Client Anwendung dazu führen, dass immer mehr Anfragen der Nutzer das System immer stärker blockieren. Ein Blockieren der Client Anwendung kann aber auch durch eine Überlastung des Netzwerks ausgelöst werden. Die Client Anwendung fühlt sich in solchen Fällen für den Nutzer träge und langsam an. Im Falle von Webanwendungen verlässt der Nutzer in der Regel dann sehr schnell die Seite.

 

Als Lösung für solche Situationen bietet der Netflix OSS das Projekt Hystrix, als sogenannte „Circuit Breaker“ Bibliothek, an. Ein „Circuit Breaker“ ist eine Sicherung, welche ausgelöst wird, sobald gewisse Umstände eintreten. Hystrix bietet darüber hinaus viele zusätzliche Funktionalitäten:

 

  • kapselt ein Kommando und bietet synchrone und asynchrone Ausführung,
  • löst nach definiertem Timeout die Sicherung aus,
  • führt jedes Kommando in einem definierten Thread Pool aus,
  • auslösen der Sicherung bei zu hoher Fehlerrate eines Kommandos,
  • ermöglicht die Ausführung eines Fallbacks im Fehlerfall,
  • erzeugt Performance Metriken,
  • ermöglicht die Nutzung eines Caches.

 

Alle diese Funktionalitäten stehen zur Verfügung, sobald ein in der Client Anwendung ausgeführtes Kommando in ein „HystrixCommand“ überführt wird. Meiner Meinung nach ist es wichtig, den nachfolgend abgebildeten Ablauf der Ausführung eines Hystrix Kommandos zu verstehen.

Abbildung .1: Netflix, Hystrix Command Fflow Chart, Web URL: https://github.com/Netflix/Hystrix/wiki/How-it-Works [Stand 2016-05-25]

Abbildung .1: Netflix, Hystrix Command Flow Chart, Web URL: https://github.com/Netflix/Hystrix/wiki/How-it-Works [Stand 2016-05-25]

Die detaillierte Beschreibung des Ablaufs finden Sie hier. Der Grund, warum ich diese Abbildung hier aufgeführt habe ist, dass diese sehr schön zeigt, dass Hystrix nicht nur ein reiner Ciruit Breaker ist. Wie zu erkennen ist, bietet Hystrix ein definiertes Verfahren zur Absicherung eines Netzwerkkommandos. Es besteht mit Hilfe der Hystrix Metriken die Möglichkeit sehr einfach und bequem Antwortzeiten auszuwerten. Durch die Integration konnten wir in unserem Projekt die Antwortzeiten eines Fedora4 Content Repository Servers, eines EMC S3 Object Storage Servers und des lokalen Dateisystems vergleichen. Die Hystrix Metriken konnten wir sehr einfach mittels des Hystrix Dashboards visualisieren und in Echtzeit auswerten. So kann auch in produktiven Umgebungen die Reaktions- bzw. Widerstandsfähigkeit einzelner Systeme optimal bewertet werden. Dies ersetzt natürlich keine umfassende Monitoringlösung, bietet aber die Möglichkeit, die Auslastung einzelner Systeme schnell zu erkennen und richtig zu behandeln.

 

Die Integration

Die Integration von Hystrix ist, wie auch bei den anderen „Platform Services“ Komponenten, einmal mittels der nativen Netflix Bibliothek oder aber auch über das Spring Cloud Projekt möglich. In unserem Projekt haben wir beide Möglichkeiten erfolgreich durchgeführt.Spring Cloud bietet eine sehr einfache und leichte Integration via Annotation:

 

Beispiel:

@HystrixCommand(commandKey = „DMS->EMCS3:findObjectContent“, groupKey = „DMS->EMCS3“)

 

Hierbei wird lediglich der Name des Kommandos und des Threadpools definiert. Es ist über die Zusatzbibliothek hystrix-javanica zusätzlich möglich, alle Konfigurationswerte direkt in der Annotation aufzuführen. Wir haben uns allerdings dazu entschieden, die Konfiguration in der zentralen „application.properties“ Datei durchzuführen.

 

Im Bereich der nativen Netflix Bibliothek ist die Integration ebenfalls sehr leicht. Nach dem Einbinden der Abhängigkeiten hystrix-core und hystrix-metrics-event-stream kann die Integration durchgeführt werden. Die Klasse, mit welcher ein Kommando im Netzwerk ausgeführt wird, muss lediglich die Klasse HystrixCommand erweitern und die Methode run() implementieren. Die Konfiguration erfolgt über die Datei „eureka-client.properties“.

Bei einigen Standardwerten der Konfiguration mussten wir Anpassungen vornehmen, da Hystrix die Sicherung für unseren Anwendungsfall zu schnell ausgelöst hat. Dies ist uns bei Belastungstests mit dem Werkzeug JMeter aufgefallen. Letztendlich konnten wir mit folgenden Einstellungen ein sehr gutes Antwortverhalten bei einer stark belasteten Komponente erzeugen:

 

hystrix.command.default.execution.isolation.strategy=THREAD

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=120000

hystrix.command.default.execution.isolation.thread.maxConcurrentRequests=1024

hystrix.command.default.fallback.isolation.thread.maxConcurrentRequests=1024

hystrix.threadpool.default.coreSize=1024

hystrix.threadpool.default.maxQueueSize=1024

hystrix.threadpool.default.keepAliveTimeMinutes=2

hystrix.threadpool.default.queueSizeRejectionThreshold=15

hystrix.threadpool.default.metrics.rollingStats.numBuckets=12

hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds=1440  

 

Sich diese Konfigurationswerte genau zu betrachten und diese festzulegen, ist ein wichtiger Schritt bei der Integration von Hystrix. Allerdings muss natürlich jeder selbst entscheiden, welche Werte für welches Kommando sinnvoll sind.

 

Fazit

Die Integration ist, wie bereits bei den anderen „Platform Services“ des Netflix OSS, nicht sehr aufwendig. Dieses Werkzeug, finde ich persönlich, wegen der vielen zusätzlichen Funktionalitäten sehr interessant und nützlich. Es bietet eine standardisierte Lösung, um ein Netzwerkkommando gesichert auszuführen, ein Fallback zur Verfügung zu stellen, einen Cache zu nutzen und Performancemesswerte zu erzeugen. In Zukunft werde ich für mich persönlich daher immer bewerten, ob nicht die Verwendung dieser Bibliothek bei jeglichen Netzwerkzugriffen eines Projektes sinnvoll ist.

0 Kommentare

Ihr Kommentar

An Diskussion beteiligen?
Hinterlassen Sie uns einen Kommentar!

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.