Hystrix & Archaius – Dynamische Konfiguration zur Laufzeit

Keine Kommentare

Wer sich mit Hystrix aus dem Hause Netflix beschäftigt und es im besten Fall auch einsetzt, ist mit sehr großer Wahrscheinlichkeit schon einmal der Bibliothek Archaius begegnet. Doch was ist Archaius und welche Möglichkeiten bieten sich mir? Habe ich vielleicht etwas im Einsatz, dessen Potenzial ich noch nicht erkannt habe? Welche Vorteile bieten sich mir bei einer dynamischen Konfiguration zur Laufzeit? Diesen und anderen Fragen möchte ich im folgenden Blog nachgehen.

Einen ersten Einblick hat euch mein Kollege Felix Braun zum Einsatz von Hystrix bereits gegeben, daher werde ich auf die Vorteile von Hystrix nicht im Detail eingehen und verweise auf seinen Artikel Fehlertoleranz statt Hochverfügbarkeit.

Dynamische Konfiguration

Wer von uns ist nicht schon durch die Deployment-Hölle gegangen und ist bei der Suche nach den richtigen Properties verzweifelt?

  • Wieso läuft das bei meinem Kollegen und nicht bei mir?
  • Welche Properties brauche ich bei der lokalen Entwicklung?
  • Wo muss die Datei liegen?
  • Wie war die URL von dem Customer REST Endpoint?

Eine deutliche Verbesserung verspricht uns hier die dynamische Konfiguration, die es uns ermöglicht, einen zentralen Ort zu definieren, unter dem wir alle Properties verwalten können. Fairerweise sei gesagt, dass dieses Vorgehen auch die ein oder andere Gefahr birgt.

Was erreichen wir durch die dynamische Konfiguration?

  • Zieladressen von Servern ändern
  • Timeouts verändern
  • Features abhängig vom Request-Context aktivieren/deaktivieren
  • Features für einen definierten Zeitraum aktivieren
  • Einfaches Service Discovery (nicht vergleichbar mit Eureka und Co.)
  • KEINE Re-Deployments der Anwendung(en) bei Konfigurationsänderungen

Archaius

archaius
Flickr: Rod Waddingtons

Archaius stammt ebenfalls aus dem Hause Netflix und wurde 2012 veröffentlicht. Wie bei allen Open-Source Projekten könnt ihr euch aktiv an der Weiterentwicklung beteiligen. Ihr findet die aktuellen Sourcen unter Archaius @ GitHub.

Dank Archaius haben wir nun die Möglichkeit einer mehrstufigen Konfiguration. Hierbei bleibt uns das gute alte Property-File erhalten und dient Archaius als Fallback-Variante. Fallback? Ja genau, Archaius kann von uns so konfiguriert werden, dass zum Start unserer Anwendung zuerst im Classpath nach einer config.properies Datei gesucht wird.

Quelle: Netflix @ GitHub
https://github.com/Netflix/archaius/wiki/Overview

Darauf aufbauend setzt Archaius auf eine Composite-Configuration. Dabei reicht die config.properties im Classpath unter „/META-INF/config.properties“ aus, um eure Anwendung zu starten und sie mit einer Default-Konfiguration zu bestücken. Wurden von uns keine weiteren Quellen definiert, unter denen Archaius nach unseren Properties suchen soll, startet die Anwendung mit den Werten aus dem Property File. Haben wir weitere Quellen definiert, werden unsere lokalen Werte überschrieben. Es werden dabei nur die Werte überschrieben, die von Archaius remote gefunden wurden. Alle anderen behalten ihren Wert.

Das folgende Code-Beispiel zeigt euch eine Composite-Configuration, die mit einem CoreOS etcd Server als weitere Quelle zusammenarbeitet.

 
AbstractPollingScheduler scheduler = new FixedDelayPollingScheduler();
 
// Step 1: init ConcurrentcompositeConfiguration
ConcurrentCompositeConfiguration compositeConfig = new ConcurrentCompositeConfiguration();
 
// Step 2: load config.properties from META-INF 
ClasspathPropertiesConfiguration.initialize();
 
// Step 3: CoresOS Etcd service configuration
DynamicWatchedConfiguration etcdConfiguration = createEtcdConfiguration();
 
if (etcdConfiguration != null)
   compositeConfig.addConfiguration(etcdConfiguration, "etcd override configuration");
 
// Step 3: put all together
ConfigurationManager.install(compositeConfig);

Ich verwende in meinem Beispiel einen CoreOS etcd Server, um meine Konfiguration abzulegen.

Archaius unterstützt dabei unter anderem die folgenden Sourcen:

  • Files
  • Remote URLs
  • JDBC
  • REST
  • AWS Dynamo DB
  • Apache ZooKeeper
  • CoreOS etcd

Auch hier habt ihr wieder die Möglichkeit, euch aktiv an der Weiterentwicklung zu beteiligen und könnt, falls notwendig, weitere Adapter schreiben und über einen Pull-Request an Netflix zurückspielen.

CoresOS ETCD

Wie bereits erwähnt, nutze ich einen etcd Server von CoreOS, um meine Konfiguration abzulegen und diese via REST Endpoint mit Archaius zu überwachen. Wenn ihr eure Applikation hochgefahren habt, wird Archaius die Quellen eurer Konfiguration in regelmäßigen Abständen abfragen und auf Veränderungen reagieren. Über die Property „archaius.fixedDelayPollingScheduler.initialDelayMills“ könnt ihr den Default Value von 30000 ms verändern.

Beispiel einer mehrstufigen Konfiguration:

Ihr habt in eurem Classpath ein config.properties File, mit der Property „beispiel.timeout=10“ gesetzt und unter der Remote URL file:///apps/myapp/application.properties den Wert „beispiel.timeout=500“ gesetzt. Nach dem Start wird eure Applikation mit einem Timeout von 500 arbeiten, da dieser aus der Remote-application.properties gezogen wird. Sollte die Remote URL nicht erreichbar sein, wird Archaius euch den Timeout Wert mit 10 liefern.

Archaius & Hystrix

Hystrix bietet uns zahlreiche Konfigurationsmöglichkeiten, bei vielen würde ein einfaches Property File ausreichen, um die Applikation vernünftig betreiben zu können. Netflix hat sich bei der Vergabe der Default-Werte auf die eigenen Erfahrungen verlassen und uns daher viele Entscheidungen abgenommen. Aber mal ehrlich, nur die wenigsten von uns arbeiten in vergleichbaren Projekten und nicht jeder Default passt zu unseren Anforderungen.

Bevor ich nun auf die Vorteile des Zusammenspiels von Hystrix & Archaius eingehe, möchte ich euch die folgende kleine Anwendung vorstellen. Die Kernaufgabe dieser Anwendung ist die Buchung von Versandaufträgen. Ein uns bekannter Kunde möchte eine Sendung zu einer Adresse verschicken und erstellt einen Versandauftrag.

Im nachfolgenden Bild ist eine mögliche Architektur skizziert und dient uns als Grundlage.

transportservice

  • Step 1: Abhol- und Zustelladresse werden geprüft
  • Step 2: Kundendaten werden validiert
  • Step 3: Kunde führt den Auftrag aus
  • Step 4: Auslesen der Kundeninfos zur Generierung der Rechnung
  • Step 5: Auslesen der Abhol- und Zustelladresse
  • Step 6: Generierung ein Connote (Frachtbriefnummer)

Die Steps 4 bis 6 werden von BookingService parallel durchgeführt und an den TransportService zurückgemeldet, dieser meldet die erfolgreiche Verarbeitung dem Kunden.
Kommen wir nun zum erwähnten Zusammenspiel von Hystrix & Archaius…

Hystrix wurde von Netflix mit einer Reihe von sehr nützlichen Defaults ausgestattet. Der zentralste Default ist dabei die Anzahl von Sekunden, die vergehen darf, bis Hystrix einen Timeout feststellt und uns mit einem Fallback antwortet. In der Transport-Applikation ist jeder Service-Aufruf mit einem Hystrix-Command abgesichert und arbeitet erstmal mit den Default-Einstellungen von Hystrix. Somit hat jeder Service 1 Sekunde Zeit zu antworten…

timeouts

Unsere Applikation wurde nun in mühevoller Handarbeit oder mithilfe eines automatisierten Build- und Deployprozesses auf unseren Server installiert. Wie ihr vielleicht festgestellt habt, hat unser BookingService ein Problem! Er wird vom TransportService aufgerufen und hat dabei 1 Sekunde lang Zeit zu antworten. Der BookingService muss aber den ConnoteService, AddressService und CustomerService aufrufen. Diese 3 genannten Service haben jeweils auch 1 Sekunde lang Zeit zu antworten. Wenn sie das aber nicht deutlich unter 1 Sekunde geschafft haben, wird Hystrix den Aufruf vom TransportService zum BookingService abbrechen und einen Fallback liefern.

Es wird nicht jeder Aufruf scheitern, dennoch ist hier die Konfiguration nicht korrekt, wir müssen uns durch Erfahrung und Tests an die optimalen Parameter herantasten. Jetzt endlich kommt Archaius ins Spiel: Durch unsere dynamische Konfiguration können wir nun auf unserem etcd Server die Timeouts zur Laufzeit ändern.

Im folgenden Curl-Command setzen wir den Timeout des TransportBooking Commands (Hystrix) auf 2 Sekunden:

# etcd base url
baseurl=http://0.0.0.0:2379/v2/keys/hystrix
 
curl -L -X PUT $baseurl/
hystrix.command.TransportBookingCmdKey.execution.isolation.thread.timeoutInMilliseconds -d value="2000"

Nach diesem Vorgehen können wir alle Timeouts während der Laufzeit konfigurieren und optimieren. Auch andere wichtige Properties können von uns zur Laufzeit angepasst werden. So ist es bei der weiteren Optimierung unserer Hystrix-Konfiguration auch wichtig, den Circuit Breaker während der Laufzeit zu aktivieren und zu deaktivieren. Nur so können wir unsere Fallbacks überprüfen und erhalten wichtige Informationen darüber, ob unsere Fallback-Strategie tragfähig ist.

Mit den beiden folgenden Curl-Commands werden die Circuit Breaker des BookingService keine Anfragen mehr an den jeweiligen Service weiterleiten und nur noch mit dem definierten Fallback antworten.

# etcd base url
baseurl=http://0.0.0.0:2379/v2/keys/hystrix
 
curl -L -X PUT $baseurl/hystrix.command.BookingConnoteCmdKey.circuitBreaker.forceOpen -d value="true"
curl -L -X PUT $baseurl/hystrix.command.BookingCustomerCmdKey.circuitBreaker.forceOpen -d value="true"

Im vorherigen Schritt haben wir Hystrix nun so eingestellt, dass der Booking Service nur noch mit den Fallbacks des ConnoteService und des BookingSerivce arbeitet. Im letzten Beispiel werden wir nun die Fallbacks deaktivieren und schauen wir unsere Architektur mit diesem Fehler umgeht.

# etcd base url
baseurl=http://0.0.0.0:2379/v2/keys/hystrix
 
curl -L -X PUT $baseurl/hystrix.command.BookingConnoteCmdKey.fallback.enabled -d value="false"
curl -L -X PUT $baseurl/hystrix.command.BookingCustomerCmdKey.fallback.enabled -d value="false"

Was passiert nun? Da wir den Circuit Breaker für die beiden Commands „BookingConnoteCmdKey“ und „BookingCustomerCmdKey“ geöffnet haben, möchte Hystrix mit einem Fallback antworten. Den Fallback haben wir im letzen Curl-Command deaktiviert, dies wird zu einer Exception führen. Mit diesem Fehler muss nun unser TransportService umgehen. Ohne Hystrix würde unser System mit den kaskadierenden Fehlern nicht umgehen können, der Fehler würde das gesamte System zum Erliegen bringen und wir könnten dem Kunden nicht mehr antworten.
Da auch unser TransportService mit Hystrix vor Fehlern und Ausfällen geschützt ist, wird er mit seinem Fallback antworten und dem Kunden eine entsprechende Alternative anbieten. Denkbar wäre zum Beispiel, den Auftrag mit allen Daten temporär abzuspeichern und zu einem späteren Zeitpunkt zu verarbeiten. Dabei ist entscheidend, dass der Kunde von all dem nichts mitbekommt. Für ihn wurde der Auftrag angenommen und es wurde ihm mitgeteilt, dass die Daten zu einem späteren Zeitpunkt verarbeitet werden und er darüber informiert wird.

Fazit

Dank Hystrix können wir unser System vor Ausfällen und Fehlern anderer Komponenten schützen. Wir können den Funktionsumfang gezielt herabsetzen (graceful degradation). Wir können schnell und in von uns definierten Zeiten antworten (fail fast), für den einen oder anderen Anwendungsfall auch mit einem leeren Ergebnis als Fallback (fail silent).
Das Verhalten im Fehlerfall einer Softwarekomponente darf nicht zufällig sein. Fallback-Lösungen müssen deshalb von der Fachseite spezifiziert werden. Es obliegt den Product Owners und Requirements Enginneers, sich Gedanken darüber zu machen, mit welchen fachlichen Defaults im Fehlerfall weitergearbeitet werden kann. Es muss also bei allen Beteiligten in der Organisation ein Bewusstsein dafür geschaffen werden, dass 100 %-Verfügbarkeitsannahmen keine Option sind – auch nicht bei skalierten Clustern.

Ich hoffe, ich konnte euch das Zusammenspiel von Hystrix & Archaius anschaulich näher bringen. Über Fragen oder Kommentare würde ich mich sehr freuen!

Benjamin Wilms

Benjamin Wilms arbeitet als IT Consultant und Software Developer am Standort Solingen. In seiner +1-Zeit beschäftigt er sich mit den neuesten Technologien aus dem Java-Umfeld und versucht, während der Entwicklung von kleinen Prototypen, ein Gespür dafür zu bekommen, ob diese neuen Technologien reif für den Einsatz in einem seiner nächsten Projekte beim Kunden sind.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

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