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