Bedeutung der galvanischen Trennung für den Betrieb

Es gibt Java-Applikationen, deren Module Komponenten zugewiesen werden und in einem EAR-File verschnürt werden, auch wenn die Anwendungen dann wie beschrieben weniger robust sind. Problematisch wird es, wenn unter mehreren Komponenten Abhängigkeiten entstehen. Diese sorgen dafür, dass die Komponente A nur noch mit Komponente B laufen kann und die galvanische Trennung ist nicht mehr gegeben. Die Schnittstellen zwischen den Komponenten sind offensichtlich und leicht zu identifizieren, denn bei entsprechender Benennung der Packages findet sich schnell der Name der Komponente A im Code von Komponente B wieder.

Eine Verletzung der galvanischen Trennung zu sehen, wird schwieriger, wenn eine 3. Komponente C dazukommt, die von Komponente A und B genutzt wird. Wenn z.B. Daten aus den Komponenten A und B in Komponente zusammengeführt werden, wird die Trennung ebenfalls verletzt. Die Verletzung sorgt nicht nur bei der Handhabung der Komponenten für Probleme, sondern auch bei der Organisation der Zuständigkeiten. Wenn die Komponenten A und B von je von einem Team betreut werden, wer ist dann für die Komponente C zuständig?

Pressebericht

Ich habe meinen ersten Pressebericht verfasst und er wurde gestern veröffentlicht. Auf der Homepage meines Arbeitgebers ist er zu finden: Zahlungsverkehr im Wandel.

Galvanische Trennung in der Softwareentwicklung

Was “Galvanische Trennung” bedeutet wird bei wikipedia ganz gut beschrieben. Aber was bedeutet es eigentlich in der Softwareentwicklung?
1. Man kann 2 System-Teile getrennt voneinander implementieren.
2. Man kann diese Teile getrennt voneinander testen.
3. Man kann diese Teile getrennt voneinander in Betrieb nehmen.

Einleuchtend, oder? Aber halt! Fehlt da nicht etwas?
Richtig – der Betrieb selbst!
Problematisch wird es, wenn zwei voneinander getrennt entwickelte, getestete und in Betrieb genommene System-Teile im Betrieb nicht mehr trennbar sind. Es kann ja nicht sein, dass 2 Leitungen, die getrennt voneinander produziert wurden, auf einer Platine überkreuz angebracht werden.

Ein typischer Fall von nicht zu Ende gedacht.

Robustes System – Auch aus Sicht von Wartung und Betreuung

Im Application-Server können mehrere EAR-Files deployed werden. Solche EAR-Files enthalten JARs und auch WAR-Files. Es sind letztlich mehrere Module, die zu einem großen Ganzen zusammengesteckt werden. Dies macht Sinn, wenn es um Systeme geht, die mehrere Module enthalten, um eine fachliche Aufgabe zu erledigen.
Es gibt die unterschiedlichsten nicht funktionalen Anforderungen an Systeme. So unter anderem auch Robustheit. Für mich bedeutet dies nicht nur für einen robusten Betrieb zu sorgen, sondern auch für robuste Wartung und Betreuung.
Wenn nun ein großes System mit einer langen Prozesskette und mehreren Prozessschritten in 2 EAR-Files verpackt wird, ist es unter Umständen für die Wartung und Betreuung nicht mehr robust, weil ein möglicher Fehler in einem Prozessschritt die komplette Prozesskette lahm legt, wenn wegen diesem Fehler eines oder beide EAR-Files neu deployed werden müssen.
Aus meiner Sicht, müssen die einzelnen Prozessschritte herausgelöst werden und bestimmte Prozessschritte in ein eigenes EAR-File verpackt werden. So ist es dann auch möglich, das System robuster zu gestalten; denn einzelne Prozessschritte können auf andere Maschinen ausgelagert werden. Fällt ein Fehler auf, kann ein Prozessschritt für kurze Zeit gestoppt werden, ohne dass andere Prozessschritte davon betroffen sind.

Übrigens: Fehler treten dann auf, wenn man sie am wenigsten erwartet. Beispiel: Nach 3 Jahren fehlerlosem Betrieb gab es eine Konstellation, die wegen eines falschen Parameters zu einer falschen Ausgabe führte.

NoSQL – Lamport Timestamps

Aktuell beschäftige ich mich mit der Problemlösung für ein Browsergame. Dieses soll kostengünstig betrieben werden können – auf einem Tomcat! Da die meisten (Cloud-)Provider vorallem Tomcat anbieten habe ich den anfänglichen Plan, einen V-Server mit einem vollwertigen Application-Server zu verwenden, verworfen.

Da CDI sehr mächtig ist und auch mit einem Tomcat nutzbar ist und als Programmiermodell in der näheren Zukunft im Bereich Java aus meiner Sicht immer mehr Anklang finden wird, ist es eine gute Übung für den beruflichen Alltag. Jede Bean kann über Dependency Injection ganz elegant von außen in eine andere Bean eingepflanzt und dort benutzt werden.

Dann bin ich auf die Problematik von Transaktionen gestoßen. Mein erster, schlichter Ansatz war, dass ich mir einen EntityManager mit Hilfe von Seam Persistence oder MyFaces CODI injecten lasse und über @Transactional dafür sorge, dass Transaktionen für Methoden zur Verfügung stehen. Ich wollte also mit JPA arbeiten. Da dies nicht so funktionierte, wie ich es mir vorstellte, aber ich die Versuche, es zum Laufen zu bringen, abgebrochen.

Aktuell suche ich mein Heil im Bereich NoSQL-Datenbanken. Einfach ein Objekt an die Datenbank übergeben und es persistiert – damit ist es nicht getan. Bei aufwändigeren Applikationen als einem reinen Archiv sollen die Daten auch verändert werden können. Und genau dort liegt der Grund für diesen Blog-Eintrag. Beim Informationen-Sammeln habe ich das Buch

NoSQL
Einstieg in die Welt nichtrelationaler Web-2.0-Datenbanken
von Stefan Edlich, Achim Friedland, Jens Hampe, Benjamin Brauer

entdeckt. Ich bin noch nicht durch, allerdings war das Kapitel 2.5 Vector Clocks besonders interessant für mich. Dort wird nämlich die Lamport-Uhr erklärt, die mich auf folgende Idee brachte:

In einem Browsergame ist die Konsistenz relativ unwichtig. Natürlich sollten die Daten zu einem Zeitpunkt konsistent sein, wann dieser Zeitpunkt ist, bleibt dabei aber unerheblich. Bei meinem Browsergame soll es vorwiegend darum gehen, Ressourcen zu sammeln, um eine Siedlung auszubauen und dadurch eine Armee erzeugen zu können, mit der man andere Siedlungen von anderen Spielern angreifen kann.

Abstrakt gesehen geschieht also in der Regel folgendes: Es wird eine Entität erzeugt an der viele Informationen hängen. Es können Informationen hinzukommen (neue Armee), aber auch gelöscht werden (Armee wird besiegt, da alle Soldaten tot). Da davon auszugehen ist, dass nicht nur ein Spieler spielt, werden mehrere Entitäten dieser Art erzeugt. Für diese Entitäten werden regelmäßig Aktualisierungen bestimmter Felder vorgenommen. Diese Felder sind in der Regel Zahlen. Mit Zahlen können diverse Berechnungen vorgenommen werden.

Und hier kommt nun die Lamport-Uhr ins Spiel: Kurz gesprochen geht es um das “Zuweisen von eindeutigen Zeitstempeln an Nachrichten” (Wikipedia). Die Lamport-Uhren erlauben allerdings nicht das Erkennen von Nebenläufigkeit. Dazu wurden die Vektorenuhren entwickelt.

Nach meinem aktuellen Wissensstand (der noch sehr gering ist) zum Thema NoSQL-Datenbanken, werden Entitäten in NoSQL-Datenbanken meist mit einem Timestamp oder einer Revisionsnummer versehen, sodass man eine Art Reihenfolge von Änderungen der Entitäten erhält. Dies geht mir persönlich nicht weit genug.

Funktionale Programmiersprachen machen es möglich, auf große Datenmengen Funktionen ausführen zu lassen – und zwar parallel! Ich möchte ungern eine Entität aus der Datenbank laden, um einen Wert zu ändern und anschließend die ganze Entität aktualisieren. Stattdessen möchte ich der Datenbank sagen können, welches Feld für welche Entität mit welcher Funktion sie aktualisieren soll. Die Datenbank nimmt diese 3 Informationen als Einheit (“Nachricht”) an und versieht sie mit einem Timestamp. Dabei ist es erstmal egal, wann diese Nachricht anschließend von der Datenbank verarbeitet wird, wichtig ist nur, dass sie verarbeitet wird! Die Reihenfolge der Verarbeitung mehrere Nachrichten wird durch den Timestamp festgelegt.

Dadurch, dass die Datenbank die Operationen verwaltet und keine Deltas ermitteln muss, lassen sich solche Operationen auch rückgängig machen, was sinnvoll für ein Browsergame ist. So könnte durch den Zugriff auf eine inkonsistente Replikation eine Operation ermöglicht werden, die auf einer konsistenten Replikation nicht möglich gewesen wäre. Bei großen Datenmengen kann das rückgängig machen einer Operation nicht manuell, sondern muss vollautomatisch geschehen. Da man allerdings nicht jede Operation rückgängig machen möchte, weil eine andere Operation Vorrang hat, müsste eine Nachricht neben dem Timestamp auch eine Priorität erhalten. So kann die Liste der Nachrichten nach zurückzurollenden Operationen durchsucht werden. Wenn bei der Synchronisierung aller Replikationen Fehler erkannt werden, können diese mit Hilfe des Timestamps und der Priorität ermitteln, welche Operationen zurückgerollt (aus der Liste gelöscht oder Umkehrung der Original-Operation) werden müssen und welche tatsächlich ausgeführt werden sollen.

Problematisch bleibt bei dieser Idee, dass es sehr viele Inkonsistenzen zwischen den einzelnen Replikationen geben könnte und dadurch viele Nachrichten zurückgerollt werden müssen.

Außerdem stellt sich mir die Frage, ob solche Funktionalität von einer Datenbank angeboten werden sollte oder über die Applikation selbst (z.B. durch die Nutzung eines Frameworks) implementiert werden muss?