Thread-Deadlocks sind eine Möglichkeit in jeder Multi-Threaded-Java-Anwendung. Sie sind ein Problem, seitdem die ersten Multi-Threaded-Anwendungen implementiert wurden. Zum Beispiel: Eine Anwendung kann durch einen vollständigen Testzyklus gehen, freigegeben werden, zusätzlichem Testen unterzogen werden, und dann schließlich für systemkritische Nutzung ausgerollt werden. Da die Nutzung der Anwendung zunimmt, beenden ein paar kritische Komponenten plötzlich die Kommunikation. Das einzige Mittel des Systemadministrators in so einem Fall ist meistens nur, die Anwendung zwangsweise zu beenden und die Anwendung neuzustarten, um sie wieder zum Laufen zu bringen.

Was gewöhnlich folgt ist, dass die Anwender der Anwendung sich beim Systemadministrator über Unannehmlichkeiten, Verkaufseinbußen und andere Beeinträchtigungen, welche durch die Stillstandzeiten verursacht wurden, beschweren. Die Anwendungsentwickler werden benachrichtigt, dass es einen Programmstillstand gegeben hat und dieses Problem umgehend behoben werden soll. Leider gibt es gewöhnlich nur sehr wenig, wenn überhaupt, Informationen darüber, was den Programmstillstand verursacht hat. Entwickler müssen Problemlösung betreiben, ohne genaue Hinweise dazu zu haben, was die Problemursache oder was das eigentliche Problem war. Dies führt oft zu einer Art Antwort wie "Versuchen Sie es bitte wieder und sehen Sie, was passiert", die für jede beteiligte Person nicht befriedigend ist.

Wenn ein Deadlock vom Wrapper festgestellt wurde, wird zuerst ein detaillierter Bericht darüber geloggt werden, welche Threads und Objekte betroffen sind. Es kann dann umgehend die JVM neu starten, um sicherzustellen, dass die Java-Anwendung mit einer minimalen Ausfallzeit wieder am Laufen ist. Das bedeutet, dass nicht nur Ihre Java-Anwendung im Betrieb bleibt, sondern alle erforderlichen Informationen, um das Problem zu melden, damit es gelöst werden kann, werden auch verfügbar sein. Deadlock

Was ist ein Deadlock?

Ein Deadlock findet statt, wenn zwei oder mehr Threads in einem Programm hängen bleiben, indem sie darauf warten, auf einen Objekt zuzugreifen, welches niemals verfügbar wird.

Stellen Sie sich zwei Arbeiter, Tom und Fred, vor. Sie beide schreiben Notizen im Beruf. Um so zu tun, müssen sie ein Block Papier und einen Stift vom Schreibtisch greifen, um die Notiz zu schreiben und dann beides den Block und den Stift auf den Schreibtisch zurückzulegen. Beide Tom und Fred sind sehr stur. Sobald sie begonnen haben, werden sie niemals den Block und den Stift auf den Tisch zurücklegen bis die Notiz zu Ende geschrieben wurde.

Was passiert, wenn Tom das Papier und Fred den Stift zur selben Zeit ergreifen? Tom wird endlos auf den Stift warten, und Fred wird endlos auf das Papier warten. Sie sind beide nun in einem Deadlock-Zustand. Es gibt keine Möglichkeit für beide fortzufahren, weil keiner von beiden nachgeben wird.

Bezüglich Tom und Fred, wird einer von beiden schließlich müde werden und das, was sie haben, zurück auf den Tisch legen. Aber Programme funktionieren nicht auf diesem Weg. Zwei Threads, die in einen Deadlock-Zustand geraten sind, werden bis in die Nacht hinein weiter warten. Zu einem bestimmten Zeitpunkt wird ihr Manager sie informieren, dass keine Notizen geschrieben wurden und es Schwierigkeiten gibt.

Was es so schwierig macht, diese Art von Deadlock-Problem zu reproduzieren and zu lösen, ist, dass es einfach ein Timing-Problem ist. Tom und Fred könnten seit Jahren ohne Probleme zusammengearbeitet haben, einfach, weil sie sehr selten genötigt waren, eine Notiz zur selben Zeit aufzuschreiben. Wenn Sie allerdings gebeten würden, mehrere Notizen in einer Minute aufzunehmen, würde das Problem ziemlich schnell auftreten.

Wie lösen wir dieses Dilemma?

Die Lösung ist, Tom und Fred dann mitzuteilen, dass dann, wenn Sie eine Notiz schreiben, sie immer versuchen müssen, den Block Papier zuerst vor dem Stift zu ergreifen. Es wird immer noch Fälle geben, wo einer von beiden immer noch einen Moment auf den anderen warten muss, um das Papier oder den Stift zurück auf den Tisch zu legen, aber sie werden niemals in eine gegenseitige Blockade kommen.

Lösung

In diesem Beispiel mit unseren zwei Arbeitern, ist das Problem sehr klar und kann einfach gelöst werden. In einer sehr großen Anwendungssoftware, die Dutzende von Ressourcen miteinschließt und Zehntausende Zeilen von Programmcode, kann es sehr schwer sein, das Problem herauszufinden, ganz zu schweigen, es zu lösen. Wahre Deadlock-Situationen können manchmal mehrere Ressourcen und Threads miteinschließen, die in Kombinationen genutzt werden und von Systementwicklern nicht vorausgesehen wurden.

Deadlocks treten von Natur wahrscheinlicher mit Live-Daten in einer Testumgebung auf, weil Live-Daten tendenziell eine breitere Vielfalt und größeren Umfang haben. Ähnlich zu Arbeitern, wenn es nur wenige Nachrichten aufzunehmen gibt, arbeitet das System ausgezeichnet. Aber wenn die Dinge sehr geschäftig werden, wird es mehr und mehr wahrscheinlich, dass ein Problem auftreten wird.

Beide Arbeiter zu bitten, den gleichen Aufgabenlisten zu folgen, scheint einleuchtend. Aber in Realität, wurden große Systeme von mehreren Entwicklern entworfen, von denen jeder seine eigene Task-Liste erstellt hat. Jeder Ablauf von Arbeitsschritten funktioniert für sich selbst ausgezeichnet, kann aber bei gemeinsamer Nutzung, im Zusammenspiel Probleme verursachen.

Während der Java Service Wrapper nicht imstande ist, einen Deadlock der Anwendungsebene zu verhindern, enthält der Wrapper erweiterte Deadlock-Erkennung-Features, die es erlauben, dass das Problem erkannt und gelöst werden kann, bevor ein Mensch wahrscheinlich jemals davon mitbekommt, dass etwas nicht stimmt. Gleichzeitig sammelt und loggt der Wrapper eine detaillierte Beschreibung darüber, was genau passierte. Dies macht es für einen Entwickler einfacher, die Problemursache zu verstehen und schnell zu lösen.

Der Wrapper hat die Fähigkeit, ohne größere Leistungseinbußen, eine komplett ablaufende Anwendung zu überwachen. Wenn er einen Deadlock in der Anwendung entdeckt, wird er in der Wrapper-Logdatei dazu einen Bericht wie folgt erstellen:

Beispiellog eines Deadlocks:
WrapperManager Error: Found 2 deadlocked threads!
WrapperManager Error: =============================
WrapperManager Error: "Worker-1" tid=18
WrapperManager Error:   java.lang.Thread.State: BLOCKED
WrapperManager Error:     at com.example.Worker1.pickUpPaper(Worker1.java:64)
WrapperManager Error:       - waiting on <0x000000002fcac6db> (a com.example.Paper) owned by "Worker-2" tid=17
WrapperManager Error:     at com.example.Worker1.pickUpPen(Worker1.java:83)
WrapperManager Error:       - locked <0x0000000029c56c60> (a com.example.Pen)
WrapperManager Error:     at com.example.Worker1.logMessage(Worker1.java:22)
WrapperManager Error:     at com.example.Worker1.run(Worker1.java:42)
WrapperManager Error:
WrapperManager Error: "Worker-2" tid=17
WrapperManager Error:   java.lang.Thread.State: BLOCKED
WrapperManager Error:     at com.example.Worker2.pickUpPen(Worker2.java:83)
WrapperManager Error:       - waiting on <0x0000000029c56c60> (a com.example.Pen) owned by "Worker-1" tid=18
WrapperManager Error:     at com.example.Worker2.pickUpPaper(Worker2.java:64)
WrapperManager Error:       - locked <0x000000002fcac6db> (a com.example.Paper)
WrapperManager Error:     at com.example.Worker2.logMessage(Worker2.java:22)
WrapperManager Error:     at com.example.Worker2.run(Worker2.java:42)
WrapperManager Error:
WrapperManager Error: =============================

Nachdem der Deadlock erkannt wurde, kann der Wrapper konfiguriert werden, einer der folgenden Aktionen auszuführen. In den meisten Fällen ist die beste Vorgehensweise, eine Benachrichtigungsemail zu senden und dann die Anwendung neu zu starten. Die Email, die die oben genannte Ausgabe enthält, macht es für den Entwickler ziemlich einfach, das Problem zu lösen. Und der Neustart hilft die Auswirkungen des Problems auf Nutzer zu reduzieren, indem die Anwendung ohne unnötige Verzögerungen wieder zum Laufen gebracht wird.

Aus dem Bericht ist sehr einfach zu erkennen, dass der Deadlock durch die Threads von "Arbeiter-1" and "Arbeiter-2" verursacht wurde, und wo genau sie in ihren jeweiligen Aufruflisten hängen blieben. Die Ausgabe stellt auch klar, welche Objektinstanzen genau fehlerhaft sind.

Zusätzlich zu allem anderen wird die JVM automatisch neu gestartet werden; das bedeutet, dass die Auswirkung auf Nutzer sich auf die betroffenen Transaktionen und kurze Augenblicke an Ausfallzeit beschränkt.

Der Wrapper hilft Ihnen, kritische Probleme zu erkennen, inklusive folgender:

Technische Lösung

Mit dem Java Service Wrapper ist es so einfach wie das Hinzufügen ein paar weniger Konfigurationseigenschaften zu Ihrer Wrapper-Konfigurationsdatei, um die Fähigkeit, Deadlocks zu erkennen, hinzuzufügen.

Die TestWrapper-Beispielanwendung, die mit dem Java Service Wrapper ausgeliefert wird, hat diese Funktionalität standardmäßig aktiviert. Starten Sie bitte einfach die Anwendung und klicken Sie auf den Button "Create Deadlock", um dies in Aktion zu sehen.

Einfache Deadlock-Erkennung

Kompatibel :3.5.0
Editionen :Professional EditionStandard EditionCommunity Edition (Not Supported)
Betriebssysteme :WindowsMac OSXLinuxIBM AIXFreeBSDHP-UXSolarisIBM z/OSIBM z/Linux

Der Java Service Wrapper macht es möglich, Folgendes zu kontrollieren :

Eine typische Konfiguration kann wie folgt aussehen:

Beispiel für das Erkennen und Loggen eines Deadlocks:
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=60
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL

Email-Benachrichtigung

Kompatibel :3.5.0
Editionen :Professional EditionStandard Edition (Not Supported)Community Edition (Not Supported)
Betriebssysteme :WindowsMac OSXLinuxIBM AIXFreeBSDHP-UXSolarisIBM z/OSIBM z/Linux

Während das obige Beispiel die Ursache eines Deadlocks loggt und dann die Anwendung wiederherstellt, ist es auch nützlich, die Problem-Benachrichtigung zu erhalten. Die folgende Konfiguration loggt den Deadlock, startet die JVM neu und sendet dann eine Benachrichtigungsmail:

Beispiel für Sendung von Email-Benachrichtigung im Fall eines Deadlocks:
# Check for deadlocks
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=60
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL

# Send notification email
wrapper.event.default.email.smtp.host=smtp.example.com
wrapper.event.default.email.subject=[%WRAPPER_HOSTNAME%:%WRAPPER_NAME%:%WRAPPER_EVENT_NAME%] Event Notification
wrapper.event.default.email.sender=myapp-noreply@example.com
wrapper.event.default.email.recipient=sysadmins@example.com
wrapper.event.jvm_deadlock.email=TRUE
wrapper.event.jvm_deadlock.email.body=A deadlock was detected in the Messaging Server.\n\nPlease check it.\n
wrapper.event.jvm_deadlock.email.maillog=ATTACHMENT

Ausführung externer Befehle

Kompatibel :3.5.0
Editionen :Professional EditionStandard Edition (Not Supported)Community Edition (Not Supported)
Betriebssysteme :WindowsMac OSXLinuxIBM AIXFreeBSDHP-UXSolarisIBM z/OSIBM z/Linux

Wenn ein Deadlock auftritt, können einige Daten in einem unaufgeräumten Zustand verbleiben, der aufgeräumt werden muss. Während der Einsatz von Transaktionen und die Sicherstellung von robusten stabilen Java-Anwendungen gewöhnlich eine gute Idee sein kann, erfordert solche Funktionalität häufig auch, dass Veränderungen seitens des Entwicklerteams der Anwendung durchgeführt werden. Systemadministratoren haben üblicherweise die Aufgabe, die Dinge zum Laufen zu bringen, während sie auf eine bessere Lösung warten.

Der Java Service Wrapper ermöglicht es, einen externen Befehl, Anwendung, oder Batch-Datei als Antwort auf Ereignisse auszuführen.

Die folgenden Konfigurationen werden:

Beispiel, um einen externen Befehl im Fall eines Deadlocks auszuführen:
# Check for deadlocks
wrapper.check.deadlock=TRUE
wrapper.check.deadlock.interval=60
wrapper.check.deadlock.action=RESTART
wrapper.check.deadlock.output=FULL

# Run external batch file in response to a deadlock.
wrapper.event.jvm_deadlock.command.argv.1=../bin/DeadlockCleanup.bat
wrapper.event.jvm_deadlock.command.block=TRUE

Verweis: Deadlock

Der Java Service Wrapper bietet einen kompletten Satz an Konfigurationseigenschaften an, die es Ihnen ermöglichen, dass der Wrapper genau Ihre Bedürfnisse abdeckt. Sehen Sie bitte in die Dokumentation bezüglich der einzelnen Eigenschaften, um alle Möglichkeiten über die obengenannten Beispiele hinaus zu sehen.