Podcast

Wenn Systeme aus dem Ruder laufen

Mit Hystrix für stabile, verteilte Anwendungen sorgen

In der fünfzehnten Folge unseres Podcasts spricht Arne Landwehr mit Stefan Tilkov über Stabilitäts-Pattern für verteilte Anwendungen und die Bibliothek "Hystrix". Arne erläutert dabei unter anderem, um was es sich bei "Circuit-Breakern" handelt und wie sie uns zu stabileren Systemen führen können.
Listen to other episodes

Shownotes & Links

Stabilitäts-Pattern:

Hystrix:

Alternative Bibliotheken:

Transkript

show / hide transcript

Stefan Tilkov: Hallo und herzlich willkommen zu einer neuen Episode unseres innoQ-Podcasts. Heute mit meinem lieben Kollegen Arne Landwehr, hallo Arne.

Arne Landwehr: Ja, hallo Stefan.

Stefan Tilkov: Arne, erzähl doch ganz kurz was über dich.

Arne Landwehr: Ja. Meine Name ist Arne Landwehr, wie du schon gesagt hast. Und ja ich arbeite seit gut eineinhalb Jahren bei der innoQ als IT-Consultant. Und fühle mich sonst in der Java-Welt zu Hause, genau.

Stefan Tilkov: Ok. Reden wollen wir heute über Stabilitätspattern, schwieriges Wort.

Arne Landwehr: Ja.

Stefan Tilkov: Und Hystrix, ein Framework, eine Bibliothek dafür. Vielleicht fangen wir mal mit ein bisschen Motivation an. Also was ist überhaupt der Kontext, in dem dieses Thema zur Sprache kommt?

Arne Landwehr: Genau. Ja um ein bisschen weiter auszuschweifen – zwar nicht gleich bei den Dinosauriern vielleicht, aber sagen wir mal vor einiger Zeit, da hat man im Wesentlichen, naja, monolithische Anwendungen entwickelt. Das heißt, wenn ich z.B. eine E-Commerce Seite gebaut habe, dann habe ich eine Anwendung gebaut, d.h., die hat sowohl die User verwaltet, als auch die Bezahlungen entgegen genommen, als auch z.B. das Inventar verwaltet. Jetzt kam im Zuge von SOA z.B., wurden diese Anwendungen immer weiter unterteilt. Das heißt, es wurden halt mehrere Anwendungen daraus gebaut, weil es einfach Vorteile hat. Also dieser Monolith hat an Nachteilen schlicht und ergreifend, dass er irgendwann unwartbar wird und dass Features, die ich dafür entwickeln möchte, immer länger dauern.

Stefan Tilkov: Ok, also das war jetzt was über Monolithen und das Zerteilen. Was hat das Zerteilen jetzt mit unseren Stabilitätspattern zu tun?

Arne Landwehr: Genau, denn das Zerteilen hört sich zwar erstmal gut an, hat auch die beschriebenen Vorteile, aber leider hat es auch ein paar Nachteile. Und einer dieser Nachteile ist halt einfach die Stabilität des Gesamtsystems, die dadurch eher schlechter wird.

Stefan Tilkov: Ok, du meinst solche Dinge, wie weil ich jetzt auf einmal Netzwerkaufrufe zwischen meinen

Arne Landwehr: Genau, das übliche. Einer fällt übers Kabel und das Netzwerk ist weg, genau.

Stefan Tilkov: Ok. Dann, lass uns zu Stabilitätspattern kommen. Woher kommt der Begriff und was verbirgt sich dahinter?

Arne Landwehr: Der Begriff stammt von Michael Nygard, aus seinem Buch Release It, was ich nur wärmstens empfehlen kann.

Stefan Tilkov: Kann ich unterstützen.

Arne Landwehr: Ja. Er zählt zum einen Stabilitätspattern auf, zum anderen hat er wunderbare Beschreibungen da drin, was man nicht tun sollte. Von daher, auf jeden Fall lesen.

Stefan Tilkov: Was wären denn Beispiele für Stabilitätspattern?

Arne Landwehr: Ja es gibt verschiedene Beispiele, z.B. das Timeout Pattern.

Stefan Tilkov: Ok, das klingt sehr trivial.

Arne Landwehr: Ja, das ist auch relativ trivial.

Stefan Tilkov: Kannst du mal erklären, was das ist?

Arne Landwehr: Ja genau. Ich habe eine Anwendung A, die ist abhängig von Anwendung B und das Timeout heißt einfach nur, dass ich nicht unendlich versuche, diese Anwendung B zu erreichen.

Stefan Tilkov: Ok.

Arne Landwehr: Sondern, bei jedem Call setze ich eben einen Timeout. Das heißt, nach einer Minute sollte ich vielleicht aufhören.

Stefan Tilkov: Ok, klingt eigentlich selbstverständlich. Ist es das nicht? Ist es nicht selbstverständlich?

Arne Landwehr: Nein, es ist leider nicht selbstverständlich, weil viele, viele dieser Librarys, die wir benutzen – z.B. der relativ bekannte Jersey-Client – haben default-Timeouts von unendlich. Das heißt, wenn ich den einfach so benutze, dann warte ich leider ewig.

Stefan Tilkov: Ok. Ok gut. Also klingt vielleicht offensichtlich, aber ist wahrscheinlich eine gute Idee, sich darüber mal Gedanken zu machen, wenn man so ein System schon aufruft. Was hast du noch an Pattern auf Lager?

Arne Landwehr: Es gibt noch das Fail-Fast Pattern.

Stefan Tilkov: Aha.

Arne Landwehr: Es ist ebenfalls relativ simpel. Es heißt auf gut Deutsch: alles, was ich vorher prüfen sollte, sollte ich auch sofort prüfen und nicht erst versuchen, eine andere Anwendung zu erreichen.

Stefan Tilkov: Ok. Das heißt, ich merke einfach, wenn was schief gelaufen ist, bevor ich alle möglichen unnötigen Dinge mache.

Arne Landwehr: Genau, genau.

Stefan Tilkov: Wenn ich nicht an meine Datenbank dran komme, brauche ich nicht vorher irgendwelche – weiß ich nicht – Objekte zu konstruieren.

Arne Landwehr: Ja. Einfaches Prinzip.

Stefan Tilkov: Ok, verstanden.

Arne Landwehr: Ist aber trotzdem in größeren Anwendungen gut im Hinterkopf zu behalten, weil es nicht ganz offensichtlich ist.

Stefan Tilkov: Bulkhead steht auf meinem Notizzettel.

Arne Landwehr: Ja, Bulkhead. Bulkhead kommt eigentlich aus der Schifffahrtsindustrie, soweit ich weiß. Heißt eigentlich nur – also z.B. es ist ein übliches Prinzip, wie Schiffe konstruiert werden. Man hat nicht einfach nur den Rumpf des Schiffes und innerhalb des Rumpfes des Schiffes ist der riesige Lagerraum ohne Unterteilung, sondern diese Schiffe sind partitioniert. Und zwar durch Schleusen und halt Korridore und Schotten. Man macht das, damit man – z.B. wenn man einen Eisberg rammt – nicht gleich das gesamte Schiff reißt und sinkt, sondern dass halt nur ein kleines Loch in die Hülle. Das kleine Loch in der Hülle wird durch diese Korridore begrenzt. Das heißt, das Wasser kann nur in dieses eine Schott einfließen und das Schiff an sich kann weiter fahren.

Stefan Tilkov: Ok. Was ist die Analogie in Software oder Softwarearchitektur?

Arne Landwehr: Klar, das Schiff ist ein komplexes System, die Software ist ein komplexes System und ich möchte halt nicht, dass wenn ein kleiner Teil meiner Software einen Fehler hat, dass dann diese gesamte Anwendung nicht mehr läuft.

Stefan Tilkov: Also was würde ich dann tun, hast du mal ein konkretes Beispiel für den Einsatz des Bulkhead Patterns?

Arne Landwehr: Ja, ich würde gern nochmal nachher, wenn wir auf Hystrix zu sprechen kommen, darauf zurück kommen.

Stefan Tilkov: Ok, einverstanden. Machen wir. Gut, was haben wir noch?

Arne Landwehr: Ja, sonst haben wir noch das Circuit-Breaker Pattern. Kommt aus der Elektrotechnik.

Stefan Tilkov: Ist das nicht einfach nur eine Sicherung?

Arne Landwehr: Ja, es ist nicht ganz “einfach nur eine Sicherung”, weil bei einer Sicherung, wenn die einmal raus fliegt – das wissen wir alle –, dann muss man zum Sicherungskasten laufen und die wieder einschalten. Der Circuit-Breaker geht ein bisschen weiter.

Stefan Tilkov: Ok.

Arne Landwehr: Der schaltet sich nämlich von alleine wieder ein.

Stefan Tilkov: Ok, das heißt, da wird einfach für eine gewisse Zeit, wird die Verbindung unterbrochen und dann wird sie irgendwann wieder hergestellt.

Arne Landwehr: Genau.

Stefan Tilkov: Warum hilft mir das bei der Stabilität?

Arne Landwehr: Ja, es ist so, wenn meine Anwendung, z.B. mein Bestellsystem von einem Preissystem abhängig ist und irgendwann ist das Preissystem nicht mehr erreichbar. Dann möchte ich nicht ständig weiter versuchen, dieses Preissystem zu erreichen. Ich möchte ja dem Preissystem die Chance geben, dass es sich wieder erholen kann und ich möchte auch bei mir keine Ressourcen blockieren. Also merke ich z.B. “Oh, meine letzten 5000 Request in einer bestimmten Zeit waren nicht erfolgreich.” Und in dem Fall merkt dann halt der Circuit-Breaker “Oh, ich sollte lieber gar nicht mehr versuchen, diese andere Anwendung zu erreichen.” In diesem Fall sagt mir dann, er wechselt seinen Status – vorher war der Status, dass der “Circuit closed” ist und er wechselt jetzt auf “Circuit open”. Und solange der Circuit open ist, werden keine weiteren Request mehr abgefeuert.

Nach einer gewissen Zeit, was man meistens konfigurieren kann – kommen wir auch vielleicht nachher nochmal kurz drauf – werden dann wieder erste Proberequest abgefeuert. In diesem Fall ist der Status des Circuits, dass er halboffen ist. Und wenn bei diesen Proberequest wieder was zurück kommt, z.B. mein Preisservice antwortet wieder, dann sage ich “Oh ja.” und ich kann jetzt meine normalen Requests wieder abfeuern dagegen und der Circuit schließt sich wieder. Sonst bleibt er halt offen.

Stefan Tilkov: Ok. Diese Muster sind wahrscheinlich, wie alle Muster, erstmal relativ abstrakt. In dem Buch von Nygard sind sie einfach beschrieben als Sachen, die man machen kann. Welche Rolle spielt jetzt Hystrix in dem ganzen?

Arne Landwehr: Ja, das stimmt. Hystrix ist praktisch eine Implementierung dieser Pattern, die ich gerade vorgestellt habe. Es gibt natürlich noch andere Implementierungen. Also nur, um sie vielleicht mal zu nennen: es gibt noch so eine kite-lib, die kann man bei Google Code finden. Es gibt auch ein Modul, innerhalb von Akka, das ebenfalls diesen Circuit-Breaker implementiert.

Genau, Hystrix selber wurde von Netflix entwickelt. Netflix kennt man, glaube ich, vor allem in Amerika, kommt aber auch immer mehr weiter zu uns rüber und ist ein großer Video-on-Demand Dienst. Und die haben eine ziemlich große Cloud-Plattform – ich habe gestern gelesen, dass die zusammen mit Youtube irgendwie für, ich glaube 45% des Internet-Traffic in Amerika verantwortlich sind. Also das ist schon wirklich, wirklich groß. Und Netflix hatte halt um 2001 rum das Problem, dass ihre Plattform relativ instabil wurde. Also auch sie hatten enorm viele Services, die alle voneinander abhängig waren und sobald ein Service ausfiel, war die Chance hoch, dass die Plattform ebenfalls nicht mehr erreichbar war. Was bei hinterher 100 Millionen Leuten, die gerne ihre TV-Serie gucken wollen, etwas schlecht ist.

Genau, es gibt noch ein konkretes Beispiel davon. Es gab bei denen einen User- Service, der war natürlich zentral. Also am Anfang muss immer geguckt werden “Ist der User registriert etc. etc.?” und immer, wenn dieser User-Service nicht erreichbar war, dann war nichts mehr halt. Dann konnte Netflix einfach keine Videos mehr aussenden.

st. Ok.

Arne Landwehr: Genau und um 2001 herum haben sie deswegen Hystrix entwickelt.

Stefan Tilkov: 2001 kann ich echt nicht glauben.

Arne Landwehr: Äh, 2011.

Stefan Tilkov: 2011. Ich habe mich schon gewundert, dass sie 2001 schon Videostreaming gemacht haben.

Arne Landwehr: Ja, die waren noch kleiner damals. Nein.

Stefan Tilkov: Ich glaube, da haben sie noch DVDs verschickt.

Arne Landwehr: Ja das stimmt, das haben sie tatsächlich gemacht.

Stefan Tilkov: Ok, wie auch immer. 2011.

Arne Landwehr: Genau. Es ist einfach so, dass wenn ich meine Anwendung absichern will, dann muss ich das eigentlich als Querschnittsfunktionalität machen. D.h., ich muss sämtliche Interaktionspunkte mit anderen Anwendungen mit Circuit- Breakern versehen. Macht man das an einer Stelle, dann implementiert man das vielleicht noch selber. Macht man das an x Stellen, dann braucht man dafür eigentlich ein Framework oder eine Library. Und das ist praktisch Hystrix.

Stefan Tilkov: Ok, also Circuit-Breaker sagst du, ist das zentrale Pattern, was da drin realisiert wird.

Arne Landwehr: Genau, genau.

Stefan Tilkov: Wie sieht das denn aus. Also wir können jetzt ein bisschen schwierig Sourcecode im Raum beschreiben, aber vielleicht – kann man das relativ kurz erklären?

Arne Landwehr: Ja, ich versuche es mal gedanklich zu skizzieren.

Stefan Tilkov: Ok.

Arne Landwehr: Also das zentrale Pattern in Hystrix ist ein Command, also das übliche Command Pattern was man aus Java kennt. Das heißt natürlich auch Hystrix-Command. Genau. Und der kapselt praktisch die Interaktion mit einem anderen System. Wenn ich wieder auf mein Bestellsystem und mein Preissystem zurück komme, heißt das einfach, mein Bestellsystem möchte mein Preissystem wie üblich aufrufen und dazu brauche ich dann halt ein Command, der das tut. Was ich dann tue, ist einfach. Ich erbe von dem Hystrix-Command, habe dann einfach ein Preisabfrage-Command implementiert, bei dem ich zwei Methoden implementieren kann bzw. eine muss ich implementieren. Was ich implementieren muss, ist die run-Methode – irgendwo muss ich ihm ja mitgeben, was er wirklich tun soll.

Stefan Tilkov: Klar.

Arne Landwehr: Genau. Und was ich noch implementieren kann, ist die Fallback- Methode. Nun ist es so, der Command wird ausgeführt mit executeexecute auf der Oberklasse praktisch arbeitet mit dem Template-Methode Pattern. Also es werden nachher die Run- und die Fallback-Methoden aufgerufen, aber was noch von dem Framework abgenommen wird, ist das gesamte Thread Handling etc. etc. und die Synchronisierung. Das ist nicht so ganz trivial und auf die Threadpools können wir gleich nochmal zu sprechen kommen.

Stefan Tilkov: Ok d.h., ich mache mir so ein Kommando. Anstatt, dass ich direkt irgendwen aufrufe, kapsele ich meinen Aufruf in ein Kommando, dieses Kommando gebe ich dann wahrscheinlich dem Hystrix zur Ausführung rüber, mit der Bitte, das für mich mal zu machen.

Arne Landwehr: Genau.

Stefan Tilkov: Und wenn der Circuit-Breaker geschlossen ist, wenn also gerade alles ganz normaler Betrieb ist, dann macht er das einfach direkt. D.h., in dem Fall bezahle ich den Overhead dafür, dass ich diese Klasse habe bauen müssen und danach eine Indirektion extra habe.

Arne Landwehr: Ja, es kommt vielleicht noch ein bisschen was dazu.

Stefan Tilkov: Ok, und zwar?

Arne Landwehr: Es kommt noch – dahinter liegt ein Threadpool. Das hat einen Grund, warum da ein Threadpool hinter liegt. Also es ist einfach so, was ich machen möchte, ist, ich möchte halt diesen Timeout haben, denn wir eben schon gesagt haben und hierzu brauche ich z.B. einen Threadpool. Ich kann nicht einfach einen Timeout auf meinen aktuellen Mainthread, z.B. von meinem Tomcat setzen.

Stefan Tilkov: Klar.

Arne Landwehr: Genau. D.h., du hast immer – was Hystrix macht ist, wenn ich einen weiteren Hystrix-Command aufmache, ordne ich den einer Gruppe hinzu und pro Gruppe habe ich dann einen Threadpool, z.B. zehn Threads. D.h., immer wenn ich diesen Hystrix-Command dann ausführe, wird er diesem Threadpool übergeben und dort ausgeführt. Wenn der Command jetzt erfolgreich ist, ist alles gut. Sollte er scheitern, dann wird die Fallback-Methode aufgerufen, sofern es denn eine gibt. Wenn es keine gibt, mache ich halt ein Fail fast und es fliegt gleich eine Exception. Sonst wird halt der Fallback aufgerufen und es werden die Metriken gespeichert. Sprich, in diesem Fall merkt sich halt Hystrix “Oh, ich habe gerade…”

Stefan Tilkov: “Es ist schief gegangen.”

Arne Landwehr: Genau, es ist schief gegangen.

Stefan Tilkov: Ok.

Arne Landwehr: Zählt hoch praktisch und dadurch wird der Circuit-Breaker hinterher entweder aktiviert oder nicht.

Stefan Tilkov: Ok. Wenn ich jetzt die Kommandos sozusagen in einem anderen Thread ausführe, muss ich ja irgendwie an mein Ergebnis wieder dran kommen. D.h., ich habe da nicht – offensichtlich habe ich das Kommando zum Execute weitergeben, das wird nicht blocken, sondern Execute kommt direkt zurück und sagt “Habe ich entgegen genommen.”

Arne Landwehr: Das ist unterschiedlich.

Stefan Tilkov: Ah.

Arne Landwehr: Das kann man einstellen. Also es gibt beide Möglichkeiten. Also es einmal den normalen synchronen Aufruf. Das ist der mit Execute praktisch. Und dann gibt es noch einen Queue-Aufruf. Der gibt mir dann ein Future zurück. Oder was man auch machen kann, ist ein observe. Observe gibt mir dann ein observable zurück, von JavaRX.

Stefan Tilkov: Das ist ja auch – RX geht zwar nicht auf Netflix zurück, aber JavaRX.

Arne Landwehr: Genau.

Stefan Tilkov: RXJava, so heißts. Ok. Machen wir sicherlich auch noch eine Episode zu.

Arne Landwehr: Können wir machen.

Stefan Tilkov: Ich muss nochmal kurz die Sachen für mich in meinem Kopf sortieren. Was du gerade erklärt hast, war, dass immer ein Threadpool notwendig ist, wegen des Timeouts, und damit natürlich gemeint, das Framework muss eine Chance haben, auf den Timeout zu reagieren und deshalb muss es das in einem anderen Thread ausführen, auch wenn ich das aus meiner Sicht synchron ausführe. Trotzdem gibt es einen Thread, damit eben das Hystrix Framework die Überwachung übernehmen kann. Darüber hinaus kann ich es auch noch queuen und sagen “Mach das, wann immer du Zeit hast.”, dann bekomme ich eben sofort ein Return zurück, dass er das gequeuet hat und kann dann selber irgendwas anderen machen. Ok. In dem Fall, in dem ich das ganze asynchron mache – ah, hast du gerade schon erklärt – bekomme ich observable oder was er haben will zurück.

Ok d.h., das Framework übernimmt jetzt meine Kommandos zur Ausführung. Wenn alles gut läuft, führt es die irgendwann aus, ansonsten schaltet es irgendwann den Circuit-Breaker in einen offenen Zustand. Was mache ich denn in so eine Fail-Methode? Was programmiere ich denn da?

Arne Landwehr: Ja, in der Fallback-Methode.

Stefan Tilkov: Fallback-Methode.

Arne Landwehr: Genau, die Fallback-Methode. Also für die Fallback-Methode gibt es halt mehrere Möglichkeiten einfach. Ich zeige einfach mal ein paar auf. Was man natürlich ganz einfach machen kann, ist, man kann ganz still und heimlich failen. In diesem Fall gibt man z.B. einfach null zurück oder man loggt einfach nur praktisch und gibt eine leere Liste zurück. Hat Vor- und Nachteile natürlich. Kann ich auch nicht immer machen, aber häufig, also sehr häufig – viel häufiger als man denkt – geht es. Z.B. bei sehr vielen Aktionen, die irgendwie Benefits für mich sind, sag ich mal. Z.B., ich möchte dem User ein Incentive anbieten, aber mein Incentive-Service ist halt irgendwie down. Und in diesem Fall kann ich sagen “Oh, wenn ich ihn nicht erreichen kann, dann hat der User in diesem Fall…”

Stefan Tilkov: Dann gibt es eben keine Incentives.

Arne Landwehr: Genau, dann hat er halt Pech gehabt. Das ist die eine Möglichkeit, genau. Die nächste Möglichkeit ist, ich kann einen normalen, statischen Default-Wert zurück geben. Wenn wir wieder bei dem Incentive-Beispiel bleiben: ich kann natürlich sagen, ich bin netter zu meinem User und sage irgenwie “Wenn ich den Incentive-Service nicht erreichen kann, gebe ich nicht null zurück, sondern ich gebe halt einen Default zurück.”, z.B. “Immer 50%”.

Stefan Tilkov: Sonderrabatt. Ich habe meine Infrastruktur vermurkst, deswegen gebe ich dir…

Arne Landwehr: Ja, genau, genau.

Stefan Tilkov: Einverstanden.

Arne Landwehr: Was man noch machen kann, ist etwas trickreichere Fallbacks. Man kann z.B. die Hystrix-Commands natürlich ineinander schachteln. Ich könnte z.B. sagen – das hat z.B. Netflix bei ihren Usern gemacht – der User-Service ist nicht erreichbar, also mache ich in meinem Fallback einen weiteren Hystrix- Command. Dieser Command versucht aus einem Cache die Userdaten heraus zu holen. Z.B. wenn der User sich eingeloggt hatte gestern, dann gehe ich mal davon aus, die Daten werden noch halbwegs stimmen, also versuche ich es aus dem Cache wieder raus zu holen. Was Netflix weiter gemacht hat, hat das noch weiter geschachtelt und hat gesagt, “Wenn das auch nicht funktioniert, dann mache ich den nächsten Hystrix-Command im Fallback und sage einfach, ich versuche es aus dem Cookie, den mir der User mitschickt, rauszuholen.”

Stefan Tilkov: Ok. Und das Framework händelt dieses Verschachteln und zählt da korrekt mit und wiederholt die Dinge. Wiederholt das Framework die Dinge von alleine oder muss ich da selber nochmal?

Arne Landwehr: Nein, es werden keine Sachen wiederholt. Also Hystrix bietet mir keinen Retry-Mechanismus. Was man z.B. dafür machen kann, ist sowas wie Sprint- Retry-Template einsetzen. Das ist eine kleine schicke Library, die würde mir das abnehmen. Aber tatsächlich ist es so, dass man häufig gerne einen Retry hätte. Den bietet mir Hystrix einfach nicht.

Stefan Tilkov: Ok, alles klar. Woran muss ich noch denken, wenn ich das programmiere? Ich habe verstanden, ich muss mir sozusagen, an den Stellen, an denen ich so ein Command einsetze, muss ich mir Gedanken darüber machen, was ich tue, wenn das nicht geklappt hat. Das ist eine gute Idee.

Arne Landwehr: Genau.

Stefan Tilkov: Das führt vielleicht dazu, dass ich mir zumindest überlege, dass ich da bewusst return null hinschreibe und eben glaube, dass das in Ordnung ist. Was sind noch Programmiermuster, die sich ergeben, wenn ich Hystrix einsetze?

Arne Landwehr: Ja also erstmal ist es so, das ist schon ein ziemlicher Eingriff, weil man plötzlich einen neuen Threadpool im Hintergrund hat. Deshalb finde ich es auch sehr gut, dass die Hystrix-API so explizit ist.

Stefan Tilkov: Ok.

Arne Landwehr: Was man hat, ich habe z.B. meine normale API oder meine normalen Anwendung mit 100 Threads in meinem Tomcat. Plötzlich sage ich allerdings nur noch, ich feuere meine Requests ab, allerdings nur noch mit einem Threadpool von zehn. D.h., man muss sich auf jeden Fall Gedanken darüber machen, wie man das skaliert. Also wie groß soll dieser Threadpool sein, den Hystrix da mit bringt. Was ich halt dadurch habe, ist so ein automatisches Throttling irgendwo. Also ich begrenze die Anzahl der gleichzeitigen Requests einfach, die ich an das andere System abgebe, im Guten wie im Schlechten. Manchmal möchte ich das, ich möchte das andere System nicht überfordern, aber manchmal ist mir das auch einfach zu langsam. Was mir da z.B. Hystrix mitbringt, ist sowas wie ein Request-Collapser. D.h., ich kann diese verschiedenen Requests, die Hystrix macht, kann ich zusammenfassen und sage “Erst, wenn zehn Requests auf einmal kommen, dann schnür mir ein Paket daraus und schick alles auf einmal rüber.”

Stefan Tilkov: Verstehe. Alles auf einmal heißt im Prinzip, dass er in einem Thread diese zehn Requests dann macht.

Arne Landwehr: Genau.

Stefan Tilkov: Nicht, dass er die dann noch zusammen bündelt. Kann ich sowas auch machen? Kann ich ihn dazu bringen noch auf irgendeine bestimmte intelligente Art und Weise diese Kommandos zusammen zu packen?

Arne Landwehr: Ja, man kann das machen. Es gibt – man kann verschiedene Strategies implementieren, z.B. auch diese Concurrent-Strategie, kann man selber implementieren und in jeglicher sophisticated Art und Weise, die man natürlich möchte.

Stefan Tilkov: Ok. Gibt es sonst noch was zu erzählen über Hystrix, über Features, die da drin sind?

Arne Landwehr: Ja, es gibt noch zwei Sachen. Also was man dazu braucht, das ganze ist ja irgendwo auch ein Betriebsthema. Also ich möchte meine Anwendung absichern dagegen, dass sie halt nicht down geht. Was ich dazu eigentlich brauche, sind zwei Sachen: a) ich muss zur Laufzeit konfigurieren können, d.h., ich muss eingreifen können, in meiner Anwendung. Und b), ich muss auch wissen, wann ich denn eingreifen möchte. D.h., ich brauche Metriken dafür. Und beides bietet mir Hystrix auch.

Also für den ersten Punkt, für die Konfigurierbarkeit, ist es so, da benutzt Hystrix von Default aus eine Library von Netflix, die einfach sagt, “Ich habe hier meinen Property oder Source, also meinen Konfigurationsbundle und ich gucke aktiv nach, ob sich da was ändert.” Immer, wenn sie da was ändert, dann ändere ich halt auch die Werte. Prinzipiell kann man fast alle Werte ändern, die man so möchte. Also man kann einstellen, man kann den Circuit-Breaker so einstellen z.B., dass er immer aus ist, dass er immer an ist. Man kann den Threadpool pro Command einstellen sogar oder pro Command-Group. Man kann sagen, wie lang die Queue sein soll, ob er überhaupt eine Queue haben soll usw. usf. Man kann natürlich die Timeouts für jeden Command einstellen, all das ist möglich.

Stefan Tilkov: Das kann ich alles im laufenden Betrieb machen?

Arne Landwehr: Dann kann man alles im laufenden Betrieb machen. Wenn man das richtig konfiguriert hat. Und was man auch – Hystrix bietet auch noch Optionen, da man vielleicht nicht unbedingt auf die Property-Library von Hystrix, nicht vielleicht die auch noch benutzen möchte, bietet es auch noch die Option, das ganze mit JMX zu exposen. D.h., ich kann relativ einfach, sämtliche Hystrix- Properties, die ich habe, einfach als JMX-Bean bereit stellen und kann dann halt mit meiner JConsole dadrauf gehen, wie bei den meisten Java-Anwendungen.

Was es auch noch gibt – was wir eben auch schon gesagt haben mit der Concurrency-Stategie, das kann ich auch machen, für diese Configuration- Strategie – ich kann auch eine Configuration-Stategie implementieren.

Stefan Tilkov: Ok.

Arne Landwehr: Da kann ich z.B. sagen – das haben wir gemacht, wir benutzen normalerweise Spring, d.h., ich kann …

Stefan Tilkov: Wir heißt in deinem Projekt.

Arne Landwehr: Genau in meinem aktuellen Projekt. D.h., man kann einfach das Spring-Environment, was man so hat, kann man als Basis oder als Grundlagen dafür nehmen.

Stefan Tilkov: Verstehe. Waren das schon die zwei Features?

Arne Landwehr: Nein, das war das erste nur. Das zweite kommt noch.

Stefan Tilkov: Wahnsinn.

Arne Landwehr: Ja. Das zweite ist einfach, wenn ich jetzt – ich muss ja wissen, wann ich was ändern möchte. Und dafür brauche ich Metriken. Und das bietet mir Hystrix auch. Also bei jedem absetzen eines Hystrix-Commands, werden auch Metriken abgesetzt. Hystrix bietet mir, ich kann diese Metriken über eine Ressource exposen praktisch, nach draußen. Und Hystrix bietet mir auch schon defaultmäßig eine kleine Single Page App, mit wunderbaren Graphen da drauf, die mir zeigen, wie viele Requests kriege ich rein, sind meine Circuits closed oder open. Welche habe ich überhaupt, welche Commands etc. etc. Und da kann ich dann relativ schnell sehen “Oh, innerhalb kürzester Zeit läuft z.B. die Queue voll.” Und dann kann ich halt sagen, ich erhöhe die Queuesize oder ich merke, ich habe zu wenig Threads konfiguriert für einen bestimmten Command, dann kann ich das ebenfalls erhöhen.

Stefan Tilkov: Und wenn ich jetzt mehrere Instanzen von so einem Ding habe?

Arne Landwehr: Ja.

Stefan Tilkov: Also ich habe mir so ein tolles Teil gebaut, jetzt habe ich das zehn Prozesse, wo jeweils 100 Threads laufen, kriege ich die dann auch gemeinsam gemanaged?

Arne Landwehr: Ja, das geht auch.

Stefan Tilkov: Ok.

Arne Landwehr: Dafür gibt es natürlich die nächste Anwendung von Netflix.

Stefan Tilkov: Verstehe.

Arne Landwehr: Ja, die haben da einen ganzen Pool von Anwendungen dafür. Das heißt Turbine, d.h. einfach, Turbine aggregiert diese Streams praktisch. Und dann kann man mit der gleichen Single Page App – das heißt dann Hystrix Dashboard, so ist der richtige Name – kann man dann halt den aggregierten Stream empfangen.

Stefan Tilkov: Ok. Das ganze ist open source, haben wir schon gesagt. Netflix legt da großen Wert drauf, die ganzen Dinger open source zu machen. Benutzen das so ein bisschen als Werbeinstrument, als Werbetrommel.

Arne Landwehr: Ja, das ist auch nicht verkehrt. Also wenn man in den Github Account von Netflix reinguckt, da liegen diverseste Projekte, es ist glaube ich auch die Apache Lizent, man kann es also auf jeden Fall auch benutzen. Genau, also es lohnt sich auf jeden Fall mal, da rein zu gucken.

Stefan Tilkov: Ich finde das auch ganz cool gemacht mit diesen Plakaten.

Arne Landwehr: Ja.

Stefan Tilkov: Da gibt es Plakate für die einzelnen Projekte, was ich ganz witzig finde, für eine Streaming-Firma.

Arne Landwehr: Genau, jeder hat seine eigenen Filmbeschreibung dabei.

Stefan Tilkov: Ok. Hängt es von was anderem noch ab. Du hast gesagt, es kann diese Netflix-Konfigurationsgeschichte benutzen. Es kann mit diesem Hystrix- Dashboard benutzt werden, um es zu monitoren. Gibt es noch Abhängigkeiten zu anderen Dingen aus dem Netflix Universum, die man braucht, wenn man es benutzt?

Arne Landwehr: Ja, es hat noch eine Abhängigkeit zu RxJava, da es in RxJava implementiert ist. Also wir benutzen Hystrix schon etwas länger und ab der Version 1.3 haben sie unten drunter praktisch alles geändert. Also die API ist gleich geblieben, deswegen haben sie die Versionsnummer auch nicht hochgezählt, aber dadrunter sind sie umgestiegen von “Plain Old Java”, auf eine vollständige Rx-Implementierung.

Stefan Tilkov: Wir müssen unbedingt mal eine Rx-Folge machen. Aber nicht mehr jetzt.

Arne Landwehr: Ja, ja.

Stefan Tilkov: Vielleicht sagst du einen Satz dazu, was sich hinter diese komischen Wort verbirgt. Aber wirklich nur ganz kurz.

Arne Landwehr: Ja. Rx ermöglicht es einfach, einen Stream von asynchronen Events relativ einfach und problemlos in Java zu verarbeiten. Ganz kurz.

Stefan Tilkov: Ok, ja cool. Passt aber ganz gut zu dem, was da innen drin halt passiert, weil so viele Events da entstehen.

Arne Landwehr: Ja.

Stefan Tilkov: Ok, das klingt alles absolut, total klasse. Gibt es irgendwelche Nachteile bei Hystrix oder ist alles nur Friede, Freude, Eierkuchen?

Arne Landwehr: Ja, also ein Nachteil springt natürlich – ich sag mal so: es kommt drauf an. Ein Nachteil ist auf jeden Fall, kann die Art der Implementierung der Hystrix-Command sein. Also es ist natürlich so, man hätte das auch anders implementieren können. Es bietet sich ja vielleicht an, eine Implementierung zu machen über AOT oder über Annotations oder sowas, was man halt kennt. Das würde weniger den eigenen Sourcecode beeinflussen. D.h., wenn man diese Hystrix-Commands einbaut, dann muss man schon wirklich, dann muss man schon was anpacken, einfach. Man muss das selber codieren.

Stefan Tilkov: Es ist invasiv, sozusagen.

Arne Landwehr: Genau, genau. Das ist allerdings nicht unbedingt ein Nachteil, weil es einen dazu zwingt, tatsächlich darüber nachzudenken.

Stefan Tilkov: Ich muss auch sagen, ich finde es keine schöne Vorstellung, dass ich da nur eine Annotation dran schreibe und dann wird magisch das gar nicht in meinem Thread, sondern in einem anderen…

Arne Landwehr: Man hat sich ja in Java schon an die Bytecode-Manipulation gewöhnt, fast.

Stefan Tilkov: Uaah, ich weiß nicht. Das klingt so, als würde man an die Methode dran schreiben remote – achso, sowas macht man ja auch in Java.

Arne Landwehr: Ja, genau.

Stefan Tilkov: Schon klar. Ja ok.

Arne Landwehr: Das ist allerdings nur so ein halber Nachteil natürlich. Was tatsächlich ein Nachteil ist, sind diese Threadpools. Man muss praktisch ein bisschen wissen, wie groß man die machen sollte. D.h., was es praktisch voraussetzt, ist entweder, man macht die erstmal am Anfang relativ groß und guckt dann in der Produktionsumgebung mittels der Metrik-Ressourcen, ob die wirklich ausgelastet sind oder nicht. Oder man hat halt irgendeine Umgebung, wo man das tatsächlich vorher testen kann. Weil es ist so, wenn man die zu sehr begrenzt natürlich, dann kann man seine Anwendung damit praktisch zum Stillstand bringen. Also man muss da wirklich aufpassen.

Stefan Tilkov: Klar, ok. Also man bezahlt mit zusätzlicher Komplexität und man bezahlt mit zusätzlichen Dingen, die gemanaged werden wollen, dafür, dass man halt möglicherweise eine höhere Stabilität hat. Auch nicht weiter verwunderlich. Wenn ich mehr Stabilität will, werde ich das nicht geschenkt bekommen von irgendwem.

Arne Landwehr: Genau, das wird einfach so sein.

Stefan Tilkov: Gut. Haben wir noch was vergessen?

Arne Landwehr: Ich bin gerade am überlegen. Es gibt natürlich noch weitere Sachen, die das Ganze bietet. Also man kann auch mal rein gucken, man muss keinen Threadpool benutzen.

Stefan Tilkov: Ok.

Arne Landwehr: Es gibt auch eine Implementierung mit Semaphoren. Die hat natürlich dann den Nachteil irgendwo, dass dieser Timeout nicht funktioniert. D.h., ich sollte das tunlichst nur tun bei Librarys, die ich kenne. Also sobald ich einen Remote-Call mache, sollte ich diese Semaphoren-Lösung nicht benutzen.

Stefan Tilkov: Ok. Alles klar. Hast du noch ein paar abschließende, kluge Worte zu den Stabilitätspattern allgemein und zu Hystrix im Besonderen?

Arne Landwehr: Allgemein kann man natürlich sagen, das Thema wird immer brennender, so wie ich das sehe. Und man sollte sich – also man sollte auf jeden Fall dieses Buch lesen.

Stefan Tilkov: Das sollte man einfach kaufen.

Arne Landwehr: Das Buch ist ein must-have einfach.

Stefan Tilkov: Der Herr Nygard hat jeden Dollar verdient, den er da bekommt.

Arne Landwehr: Und man sollte vielleicht einfach mal seine Anwendung, die man aktuell vor sich hat, auf diese Pattern abklopfen. Die ersten, sie klingen sehr trivial. Trotzdem ist es so, dass fast alle Anwendungen, die ich bisher gesehen habe, es nicht konsequent durchziehen, schlicht und ergreifen. Und je größer der Anwendungszoo wird, den man hat, desto instabiler wird das ganze einfach. Und auch wenn sich der Hystrix, auch wenn sich der Circuit-Breaker am Anfang nicht so wahnsinnig komplex anhört, wirklich selber implementieren möchte man das eigentlich auch nicht. Von daher ist sowas wie Hystrix auf jeden Fall eine gute Wahl.

Stefan Tilkov: Sowas wie Hystrix. Müsste ja nicht unbedingt Hystrix sein.

Arne Landwehr: Nö, es müsste nicht unbedingt Hystrix sein. Z.B. wenn man selber Akka schon einsetzt, dann wäre es auf jeden Fall klug wahrscheinlich, auch den Circuit-Breaker von Akka einzusetzen.

Stefan Tilkov: Ok. Aber es gibt auch keine negative Grundsatzaussage zu Hystrix oder so.

Arne Landwehr: Nein, also wir hatten noch in der früheren Version von Hystrix war natürlich der ein oder andere Bug drin. Manchmal kam ein null zurück, wo kein null zurück kommen sollte. Aber seitdem sie das auf RxJava umgebaut haben, hatten wir bisher keinerlei Probleme. Ja, von daher. Es ist manchmal etwas tricky, weil natürlich wird Hystrix bei Netflix selber verwendet. Das merkt man an der ein oder anderen Stelle. Also es ist natürlich z.B. möglich, über diese Strategies Sachen auszutauschen, aber es ist leider nicht komplett möglich, deswegen auf alle Netflix-Abhängigkeiten zu verzichten. Das funktioniert einfach nicht ganz. Wenn es mehr eingesetzt wird, bei anderen Projekten, denke ich, wird das auch noch sich ändern.

Stefan Tilkov: Ok, gut. Arne, vielen Dank. Sehr spannendes Ding. Ich habe eine Menge gelernt, das sind immer meine Lieblingspodcastfolgen, wo ich so richtig schicke, neue Sachen lerne. Danke dir und Dank an die Hörer.

Arne Landwehr: Vielen Dank Stefan.

Stefan Tilkov: Bis dann, ciao.

Senior Consultant

Arne Landwehr feels at home in the Java universe. Prior to joining INNOQ, he worked as a software architect and team lead. Besides focusing on clean code, Arne is interested in design and architecture of distributed systems.

In Memoriam ∞ CEO & Principal Consultant

Stefan was a founder and Principal Consultant at INNOQ Germany, where he spent his time alternating between advising customers on new technologies and taking the blame from his co-workers for doing so. He was a frequent speaker at conferences and author of numerous articles.

We mourn the loss of Stefan.