tech-trends

// 01-06-2021

Mit diesem Artikel möchte ich meine Erfahrungen im Bereich Troubleshooting von Java Applikationen teilen. Ich habe versucht den Artikel so wenig technisch wie möglich zu gestalten und richte mich gleichermaßen an Entwicklung, Betrieb und Management.

Vorweg eine Frage: Wie viel ist es Ihnen wert Fehler in Produktion zu erkennen und anschließend schnell und dauerhaft zu beheben?

Oder anders gefragt:
Wie viel kostet es Sie, wenn Ihre Applikation eine Stunde ausfällt? 

Fehlerbehebung sollte nicht zu Symptombekämpfung werden. Der Applikation mehr Speicher zu geben oder die Applikation in regelmäßigen Abständen neu zu starten ist keine Fehlerbehebung. Es wird mit der Zeit nicht besser werden.

Ein besonderer Troubleshooting Einsatz 

Starten möchte ich mit einem Troubleshooting Einsatz der besonders (kurz) war. 

Troubleshooting ist in der Theorie recht einfach: 

  • Ruhe bewahren und versuchen das Problem zu verstehen
  • Daten sammeln und Notfallmaßnahmen einleiten (z.B. Neustart)
  • Daten auswerten
  • Eine Hypothese aufstellen, wie man das Problem beheben könnte
  • Maßnahmen setzen
  • Maßnahmen überprüfen, ob sie helfen

Ja -> Super!
Nein -> Zurück zum ersten Punkt

Bei diesem Troubleshooting Einsatz wurde das Problem verstanden, es konnten jedoch keine Daten gesammelt werden. Es gab kein Monitoring, kein Applications Logging, keine GC Logs, keine JDK Installation (nur JRE, somit fehlen Tools wie jstat, jstack, jcmd) und somit auch kein Troubleshooting.

Eine der ersten Fragen, die ich beim Troubleshooting stelle: Was hat sich geändert?

Können Sie mir diese Frage beantworten? Deswegen ist es so wichtig Daten vom ersten Tag anzusammeln und eine gewisse Zeit aufzubewahren.

Daten sammeln

Um Daten sammeln zu können, benötigt es viel Speicherplatz. Sorgen Sie dafür, dass immer genügend davon da ist.

Logs

Hier gilt: So wenig wie möglich, so viel wie nötig. Logs  verbrauchen sehr schnell, sehr viel Speicherplatz. Regelmäßig Logs zu konsolidieren und nicht benötigte Logmeldungen zu entfernen oder in einen anderen Log Level zu schieben spart viel Speicherplatz. Wichtig ist auch, dass der Log Level während des Betriebs angepasst werden kann, ohne die Applikation stoppen zu müssen. Speziell in verteilten Systemen möchte man Logs an zentraler Stelle haben. Lösungen wie z.B der ELK Stack haben sich als sehr nützlich erwiesen. Falls Logfiles verwendet werden, sollte eine Abschätzung des Speicherplatzes gemacht und die Umgebung dementsprechend dimensioniert werden. Umgekehrt ist die Speicherlimitierung bei der Logging Konfiguration zu berücksichtigen.

Denn wie hoch ist der Nutzen von Logs, wenn sie nicht weiterverwendet werden? Eher gering. 

Verwendet man z.B. den ELK Stack können in Kibana hervorragend Dashboards erstellt werden. Je nach Abteilung können diese Dashboards eine andere Sicht auf die Applikation haben. Der Betrieb möchte wissen, dass ein Fehler aufgetreten ist. Developer müssen den Fehler nachvollziehen und die Security Abteilung möchte mögliche Angriffe erkennen. Für das Management sind ebenfalls interessante Metriken möglich!

GC Logs

Garbage Collection Logs sind eine einfache Art Daten über Speicherverhalten der JVM zu bekommen und sollten immer aktiv sein. Um GC Logs auch über einen längeren Zeitraum zu behalten, muss dies konfiguriert werden. Kurz gesagt, die Rotation der Logfiles überschreibt alte Logs. Auch bei einem Neustart der Applikation werden die alten GC Logs überschrieben. Sehr gut beschrieben ist es in diesem Beitrag.

JDK

Oracle bzw. OpenJDK kommt mit vielen nützlichen Tools. Diese Tools sind jedoch nur in der JDK und nicht in der JRE Version verfügbar. Auch wenn JDK Java Development Kit bedeutet, sollte es in der Produktionsumgebung verwendet werden.

JStat

jstat ist ein einfaches Tool, um wie bei GC Logs, Informationen zu Speicherverhalten der JVM zu kommen. jstat ist sehr nützlich, um Live zuzuschauen wie sich der Speicher verhält.

JStack

jstack verwendet man, um einen Thread Dump der JVM zu machen. Man erfährt also, welche Funktionen die Applikation gerade bearbeitet. Mit einem Thread Dump erkennt man, ob sich Threads gegenseitig blockieren, ob ein Thread stecken geblieben ist (mit mehreren Thread Dumps) oder auch welcher Thread gerade viel CPU benötigt. In Linux gibt es den Befehl “top”. Mittels “top -H” werden die Threads zum Prozess angezeigt. Die Thread ID kann umgerechnet und mit dem Thread Dump verglichen werden. Minütliche Thread Dumps sind eine einfache Möglichkeit Daten über einen längeren Zeitraum zu sammeln und sie sind sehr nützlich bei der Fehleranalyse. Grundsätzlich sind Thread Dumps schnell erstellt. Aber Achtung, wenn der Thread Dump erstellt wird, wartet die JVM auf einen Safe Point aller Threads. Bei sehr vielen Threads kann es im Sekundenbereich liegen.

JMap

jmap ermöglicht es einen kompletten Speicherabzug der JVM zu erstellen. Den Speicherabzug analysiert man am besten mit MAT (Eclipse Memory Analyser). Im Prinzip hilft MAT herauszufinden, welche Objekte den meisten Speicher verbrauchen, bzw warum Objekte bei einer Garbage Collection nicht aufgeräumt werden. Je größer der Speicher der JVM ist (Xmx), desto länger brauchen die Erstellung und die Analyse des Heap Dumps. Wichtig ist auch, dass genügend freier Speicherplatz auf der Umgebung verfügbar ist. Als Faustregel gilt:  Xmx * 1,5. Ein Heap Dump lässt sich auch hervorragend komprimieren.

Java Flight Recorder

Der Flight Recorder ist ein Java Profiler und kommt mittlerweile mit OpenJDK gratis mit. Ein Flight Recording lässt sich während des Betriebs der Applikation starten und wird mit der Java Mission Control ausgewertet. Versuchen Sie auch mal während der Entwicklung ein Flight Recording zu erstellen. Sie werden überrascht sein, welche Einblicke und Ergebnisse Sie erhalten.

APM

Mit den oben genannten Tools und Methoden können Sie einen Großteil, wenn nicht sogar alle Bereiche abdecken. Es gibt am Markt auch kostenpflichtige Tools, welche nicht unerwähnt bleiben sollen.

Dynatrace und AppDynamics sind sehr gute Lösungen, um weitere Einblicke in die Applikation zu bekommen. Geschulte Personen holen viele Informationen aus diesen Tools. Leider habe ich auch schon gesehen, dass für diese Tools viel Geld bezahlt wurde, ohne dass sie genutzt wurden.

Daten auswerten

Daten zu haben ist gut. Daten auszuwerten besser. Es muss nicht gewartet werden bis es zu Problemen in Produktion kommt. Sieht der Betrieb z.B. erhöhte Antwortzeiten eines Services oder einen Anstieg des Memory, kann bereits mit der Auswertung begonnen werden. Auch einen Vergleich zu haben wie eine gesunde Applikation aussieht, um diese mit einer fehlerhaften Applikation zu vergleichen, ist sehr hilfreich. Eine Routine aufzubauen hilft dann bei wirklichen Problemen. Es wird geübt wie die wichtigsten Daten gesammelt und ausgewertet werden. Zu wissen, wer zu verständigen ist und wer mit welchen Daten etwas anfangen kann verkürzt Stehzeiten. 

Oder um es mit einem Beispiel aus dem “wirklichen” Leben zu beschreiben: Wenn es bei Ihnen daheim brennt und Sie rufen die Feuerwehr, würden Sie dann wollen, dass die Person am anderen Ende des Hörers die Kontakte der Feuerwehrleute im Telefonbuch nachschauen muss und die Feuerwehrleute selbstständig die Adresse herausfinden müssen wo es brennt?

Im Team Schwachstellen zu analysieren und ständig kleine Verbesserungen einzubauen, hilft die Applikation stabil zu halten. Es entsteht ein gemeinsames Verständnis über die Applikation. Unter Stress das erste Mal einen Heap Dump zu analysieren macht keinen Spaß.

Zuständigkeiten

Das ist vermutlich der schwierigste Punkt. Im Internet werden Sie die lustigsten Memes finden wie z.B. “Works in Dev, Ops Problem now”.

Bei Fehlern in Produktion ist die Antwort auf die Frage wer zuständig ist einfach: ALLE!

Eine Person, die sich mit allem, also der Applikation, Java, Filesystem, Netzwerk, Datenbank, Betriebssystemen, usw. auskennt, gibt es nicht. Was können nun aber die einzelnen Personen bzw. Bereiche tun?

Das Management sollte den oben genannten Themen mehr Bedeutung und Priorität einräumen und ihren Mitarbeiter*innen deren Wichtigkeit vermitteln. Ausbildung und Trainings sind notwendig. Applikationen, Tools und Frameworks müssen regelmäßig aktualisiert werden. Planen Sie im Projekt oder Sprint Zeit dafür ein.

Kluge Sprüche zum Schluss

Normalerweise halte ich mich an YAGNI. (You ain’t gonna need it) Es gibt aber noch einen anderen Spruch: Better safe than sorry.

Beim Betrieb von Anwendungen in Produktion halte ich mich lieber an die zweite Aussage. Für einen sorglosen Betrieb müssen alle an einem Strang ziehen. Niemand will Probleme in Produktion haben. Da wir aber in einem komplexen Umfeld arbeiten, werden Fehler in Produktion auftreten. Live with it, be prepared!

Benötigen Sie Unterstützung beim Troubleshooting oder bei der Implementierung eines Prozesses bzw. Tool Sets?
We live for it, we are prepared!

// Autor

Herbert