Rainer Jung
Troubleshooter
oder Troublemaker ? Der Entwickler und seine Feuerwehr
- Aufwärmrunde
- Typische Problemsituationen
- Beobachtbarkeit und Beobachtung
- Zusammenfassung
Abstrakte Problembeschreibung
Performance-Probleme
- Anwendung ist zu langsam (einzelne Vorfälle)
- es bilden sich Staus (in Folge ist die
Anwendung nicht mehr erreichbar)
Stabilitätsprobleme - Anwendung reagiert nicht mehr
Nicht betrachtet: Probleme der fachlichen Korrektheit
Mögliche Rahmenbedingungen - Probleme treten sporadisch auf, kein Muster bekannt: Reproduktionschancen schlecht
- Probleme treten zu Hochlastzeiten auf: Reproduktionschancen besser
- Probleme treten nach einiger Zeit auf:
Reproduktionschancen unklar
Ausgangslage
a) schlechte Beobachtbarkeit - Umkehrschluss: Probleme mit guter Beobachtbarkeit
lösch die Kunden alleine
b) häufig Überlagerung mehrer Probleme
a) + b) => Es ist extrem wichtig, echte Beobachtungen von vermuteten Ursachen zu unterscheiden
Typ 1: Locking als Problemursache
Locking/Synchronisation ist nicht böse, sondern absolut notwendig!
aber: - Die Lock-Belegung darf nicht zu lange dauern
- Die Akquisitionsrate darf nicht zu hoch sein
- Genauer: das Produkt aus beiden muss
deutlich kleiner als 1 sein
Beispiele - Mittlere Belegung: 10 µs, 2.000 Locks/Sekunde -> ok
- Mittlere Belegung: 5000µs, 4 Locks/Sekunde
-> ok
Mögliche Auswirkungen von Lock-Problemen
Sonderfall Deadlock
Lock-Contention - Quasi-Serialisierung eines Teils der Anwendung
- Performance-Engpass auf Multi-CPU/-Cores-Hardware
- Das Problem tritt nicht-linear auf
Thread-Starvation - Vor allem bei stark genutzten Locks
- Einzelne Threads bekommen den Lock nicht oder zu selten
- Es gibt Locks mit Fairness, aber: Fairness
bedeutet komplexer Code (langsam), kann konträr zum OS-Scheduler sein (langsam),
erhöht also in der Regel die Log-Contention
Locking-Regeln
Vermeidung Lock-Contention - kleine komplexen Operationen während ein Lock gehalten wird
- weniger Informationen sharen, mehr echte Unabhängigkeit
- Beschäftigen Sie sich mit den Möglichkeiten
von JSR-166: Concurrency Utilities
Häufig Probleme auch in Hilfsbibliotheken
Vermeidung von Deadlocks - Total Lock Ordering
- In der Regel aber kein allgemeines Rezept,
sondern fallbezogene Lösung
Wie finden wir Lock-Probleme? - Thread-Dumps
Typ 2: Sizing
Viele Anwendungen haben Komponenten, die konfigurierbare Größen haben
Bei Produktionsstart häufigstes Sizing: Default
Manchmal auch; pi mal Daumen, dann aber nmicht konsistent
Verständlich ist - schlechtes Sizing wegen mangelnder Vorerfahrung
- schlechte Dokumentation
aber nicht: - fehlende Beobachtung
Zusatznutzen der Produktionsbeobachtung - entstehende Erfahrung zu sinnvollem
Sizing
Hier ist ein Zusammenspiel von Entwicklung und Betrieb nötig
Typ 3: Remote-Probleme
Performance-Probleme bei verteilten Systemen
Beobachtbarkeit von zentraler Bedeutung
Hier reicht jedoch ein Thread-Dump nicht aus
Bei Problemanalyse zwischen grob-granularen Komponenten ist Logging sehr hilfreich - insbesondere bei Remote Calls und Wechsel
von Technologie und/oder Zuständigkeit
Typ 4: Ressourcen-Engpass
Anwendungen nutzen Hardware-Ressourcen - CPU, Netz, Platte
Beobachtung und Analyse der meisten Engpässe bei HW-Ressourcen ist recht gut verstanden
Beobachtung und Analyse von Engpässen
im Bereich Memory ist weniger gut verstanden
- mehrere Schichten Speicherverwaltung
- virtuelles Memory
Java-Memory und Garbage Collector - viele Konfigurationsmöglichkeiten
- aber wenig gute Dokumentation (korrekt und umfassend)
- Beobachtbarkeit: ganz schlecht
- GC-Logging vor Java 6: sehr schlecht,
ab 6 Update 4 wenigstens mit Zeitstempel
Ressourcen-Virtualisierung - auch bei den gut verstandenen Ressourcen
wird es durch Virtualisierung zu Problemen kommen
Thread-Dumps
Momentaufnahme der Code-Ausführung in der JVM
Liste aller Threads - mit Name und ID, sowie Zusatnd (etwa runnable)
- mit kompletten Funktionsstack der Java-Methoden
- mit Informatioen bzgl. des Wartens auf Locks
- mit Ausgabe, ob Deadlock vorliegt
Momentaufnahme - meist muss man mehrere Aufnahmen machen,
um Zufallsbeobachtungen auszuschließen
Thread-Dumps sind ein JVM-Features und gehen sehr schnell, auch in Produktion ok, auch regelmässig (z. B. stündlich)
Dump landet im STDOUT, sollte also mit Startskript aufgefangen werden - oder Service-Wrapper verwenden
Tipp: Tanukisoft Service Wrapper für Windows
Dump-Auswertung - meist sehen wir uns zunächst nur die obersten 5-10 Methoden des Stacks an
- Threads gruppieren, deren top-n Methoden-Stack gleich ist
- Auswerteskript!
- Hypothesen im vollen Dump überprüfen
Phänomene, die sich meist gut durch Thread-Dumps verstehen lassen: - Anwendung ist langsam, obwohl die CPU-Auslastung gering ist
- CPU-Auslastung ist zu hoch
- Anwendung reagiert nicht mehr
Thred-Dumps: Vorschläge - auch mal in Produktion machen, wenn es noch keine Probleme gibt
- versuchen sie, Dumps zu verstehen
- nicht von Größe abschrecken lassen
- dem Betrieb erklären, wozu das gut ist
Logging
Performance und Erfolgsprotokolierung an den Schnittstellen
Vergeben Sie eindeutige Vorgangs-IDs
JMX
Monitoring - Störungen feststellen und melden
- kontinuierliche Messung von Betriebszuständen
Zusammfassung
Die häufgstien Produktionsprobleme sind - Performance-Probleme
- Stabilitätsprobleme
Wir brauchen auch Beobachtungen aus "guten" Zeiten
Beobachten mittels - Thread-Dumps
- Logging
- Monitoring
Lasttests von Produktionsaufnahme sinnvoll
Probleme werfen ihre Schatten voraus, also vorher hinsehen
Brücke zwischen Entwicklung und Betrieb bauen