adesso

„Hilfe, unser System hängt

7. September 2017 | von Eric Hambuch

Im laufenden Produktivbetrieb einer großen Anwendung kann es leicht passieren, dass eine Anwendung ein ungewöhnliches Verhalten zeigt, nicht mehr auf Benutzereingaben reagiert oder zunehmend langsamer wird. Im ersten Teil meiner Blog-Reihe zeige ich euch, welche Gründe es dafür geben kann und gebe euch einige Tipps, damit euer System wieder fehlerfrei läuft.

Komplexität und viele Services

Gerade in großen, über Jahre gewachsenen Anwendungen gibt es niemanden mehr, der den Überblick über die fachlichen Prozesse, die vielen Services und die Aufrufketten in der Anwendung hat. Doch was passiert, wenn mehrere Benutzer auf den gleichen Daten arbeiten möchten?

Speicherlöcher und selbstgebaute Frameworks

Ein Klassiker, den jeder von euch sicherlich kennt, sind Speicherlöcher – sogenannte „memory leaks“, die nach und nach dafür sorgen, dass sich der Hauptspeicher füllt, bis nichts mehr geht. In Zeiten ausgereifter Frameworks, bei denen man sich mehr auf Fachlichkeit als auf Technik konzentrieren kann, kommt dies jedoch nicht mehr so häufig vor.

Ihr habt nicht versucht, euer eigenes Spring-Framework zu entwickeln, einen In-Memory-Cache zu schreiben oder in einer EJB parallele Threads zu öffnen? Dann ist alles gut.

Parallelität und Sperren

Ein Applikationsserver – in den meisten Fällen die Datenbank – steuert und synchronisiert alle parallelen Zugriffe auf gemeinsam genutzte Ressourcen - zum Beispiel Datensätze in einer zentralen Datenbank. Wenn nun zwei Benutzer gleichzeitig ein Objekt ändern wollen, darf der erste Nutzer Änderungen durchführen, während der zweite warten muss. Dazu werden Sperren auf den angeforderten Ressourcen gesetzt, sodass jeweils nur ein Benutzer zur gleichen Zeit die Daten ändern darf. Am Ende der Transaktion ist alles wieder in einem konsistenten Zustand und freigegeben für alle anderen User – das sogenannte ACID-Prinzip (atomicity, consistency, isolation und durabilit).

Und wenn es dann klemmt?

Was passiert nun, wenn zwei Benutzer gleichzeitig, aber in unterschiedlicher Reihenfolge auf die gleichen Objekte zugreifen wollen? Schauen wir uns ein Beispiel an: Benutzer 1 sperrt „Julia“, Benutzer 2 sperrt „Klaus“, dann versucht Benutzer 1 ebenfalls „Klaus“ zu sperren – und muss warten. Gleichzeitig versucht Benutzer 2 ebenfalls „Julia“ zu sperren und der Deadlock ist komplett.

Normalerweise erkennt die Datenbank hier den Deadlock und löst einen entsprechenden Fehler aus. Doch schon im dritten Schritt kann sich eine Verzögerung ergeben, wenn beide Benutzer länger laufende Transaktionen ausführen.

Was ist also zu tun?

In solchen Fällen habt ihr nur die Möglichkeit, die entsprechenden Transaktionen abzubrechen und zurückzurollen. Dann geht es in die Analyse der verschiedenen Logfiles – sowohl der Datenbank als auch der Anwendung – um die betroffenen Use Cases zu identifizieren.

Schlussendlich müssen die Softwareentwickler an die Anwendung ran und:

1. die Reihenfolge der Sperranforderung einheitlich machen. Fordern alle Use Cases die Sperren immer in der gleichen Reihenfolge an – beispielsweise aufsteigend nach ihrem Primärschlüssel − so kann es erst gar nicht zu Deadlocks kommen.

2. mehr optimistisches als pessimistisches Locking einsetzen, denn damit wird die Dauer von exklusiven Sperren reduziert.

3. die Dauer von langlaufenden Änderungen minimieren, indem beispielsweise alle Änderungsvorgänge am Ende einer Transaktion gesammelt geschrieben oder Use Cases über mehrere Transaktionen aufgesplittet werden - falls dies möglich ist.

4. als letzte Möglichkeit sollte auch ein Redesign der Anwendung in Betracht gezogen werden, um die Use Cases und damit die Datenzugriffe neu zu strukturieren.

Sind Anwendungen über die Jahre gewachsen, kommt es leicht vor, dass durch zahlreiche Erweiterungen die Sperr- und Aufrufreihenfolgen von Objekten und Services durcheinander geraten sind. Dann wird es höchste Zeit für ein umfangreicheres Refactoring.

Für heute sind alle Probleme gelöst und eure Anwendung läuft wieder flüssig und störungsfrei.

In meinem nächsten Blog-Beitrag werde ich mich mit Effekten, die durch Prüfung der referentiellen Integrität in Datenbanken auftreten können, befassen.

Wenn ihr mehr zu diesem Thema erfahren möchtet, werft einen Blick in meinen im PHP Magazin erschienenen Artikel „Das muss das System abkönnen! Stabilität verteilter Systeme in komplexen Anwendungslandschaften“ oder schaut auf der adesso-Website vorbei.

Autor Eric Hambuch
Kategorie: Fachthemen
Tags: Software | Komplexität | Datenbanken

Eric Hambuch ist Competence Center Leiter für Java-Entwicklung bei adesso in Dortmund. Seit mehr als zehn Jahren entwickelt, analysiert und optimiert er komplexe JEE-Systeme und hat bisher jedes System wieder zum Laufen bekommen.

Diese Seite speichern. Diese Seite entfernen.