bachelor-thesis/chapters/thesis/chapter03.tex
2024-06-02 15:43:11 +02:00

204 lines
14 KiB
TeX

\chapter{Konzept}
\label{ch:concept}
Das folgende Kapitel enthält die im Rahmen dieser Arbeit entstandenen Konzepte, um die aktuellen Probleme aufzuzeigen.
Hierbei sind verschiedene Vorgehen zu verwenden, da die Anwendung aktuell noch nicht als produktive Anwendung
freigegeben ist. Zum einen werden die aktuelle Mitarbeiter befragt, zu anderen wird der Produktionsserver selbst
überprüft. Danach wird die Anwendung an sich untersucht und zum Schluss wird eine Neuentwicklung mit Hilfe anderer
Frameworks diskutiert.
\section{Allgemeine Betrachtung des Systems}
\label{sec:concept:viewsystem}
Für die Untersuchung des Systems wird der direkte Zugang zum Server benötigt. Hierbei werden zuerst die im Kapitel
\ref{sec:basics:services} beschriebenen Einstellungen überprüft.
Zuerst wird am PostgreSQL"=Server die Konfiguration der Speicher mit der Vorgabe für Produktivsystem abgeglichen.
Hierunter fallen die Einstellungen für die \textit{shared\_buffers}, der bei einem Arbeitsspeicher von mehr als 1 GB
ca. 25\% des Arbeitsspeicher definiert sein soll \cite{PostgresC20.4:2024}.
\mytodos{die anderen Speicher abarbeiten?}
Dann wird mit dem Systemtools, wie den Konsolenanwendungen \textit{htop} und \textit{free}, die Auslastung des Servers
überprüft. Hierbei ist die CPU-Leistung, der aktuell genutzte Arbeitsspeicher, sowie die Zugriffe auf die Festplatte
die wichtigen Faktoren zur Bewertung.
Die CPU-Leistung sollte im Schnitt nicht die 70\% überschreiten, für kurze Spitzen wäre dies zulässig. Da sonst der
Server an seiner Leistungsgrenze arbeitet und dadurch es nicht mehr schafft die gestellten Anfragen schnell genug
abzuarbeiten.
Da unter Linux der Arbeitsspeicher nicht mehr direkt freigegeben wird, ist hier die Page-Datei der wichtigere Indikator.
Wenn dieses in Verwendung ist, dann benötigt die aktuell laufenden Programme mehr Arbeitsspeicher als vorhanden ist,
wodurch der aktuell nicht verwendete in die Page-Datei ausgelagert wird. Hierdurch erhöhen sich die Zugriffszeiten auf
diese Elemente drastisch.
Die Zugriffsgeschwindigkeit, die Zugriffszeit sowie die Warteschlange an der Festplatte zeigt deren Belastungsgrenze auf.
Hierbei kann es mehrere Faktoren geben. Zum einem führt das Paging des Arbeitsspeicher zu erhöhten Zugriffen. Ein zu
klein gewählter Cache oder gar zu wenig Arbeitsspeicher erhöhen die Zugriffe auf die Festplatte, da weniger
zwischengespeichert werden kann und daher diese Daten immer wieder direkt von der Festplatte geladen werden müssen.
\section{Untersuchung der Anwendung}
\label{sec:concept:softwarestructure}
Bei der Performance-Untersuchung der Anwendung, wird sich im ersten Schritt auf die Dokumentenliste beschränkt. Anhand
dieser können die Optimierungen getestet und überprüft werden. Im Nachgang können die daraus gewonnen Kenntnisse auf
die anderen Abfragen übertragen werden.
Die Dokumentenliste zeigt direkte und indirekte Informationen zu einem Dokument an. Hierzu gehört die Kennung des
Dokumentes, das Schreibdatum, der Autor, der Adressat, der Schreibort und die Korrespondenzform. Nach jeder dieser
Information kann der Bediener die Liste auf"= oder absteigend sortieren lassen. Zusätzlich wird die Liste immer nach
dem Schreibdatum sortiert, um die Ergebnisse bei gleichen Werten der zu sortierenden Informationen, wie dem Schreibort,
immer in einer chronologisch aufsteigenden Form zu darzustellen.
Aktuell verwenden die Editoren die Dokumentenliste um die Briefe eines Adressaten zu filtern und diese in
chronologische Reihenfolge aufzulisten und zu untersuchen wie Kommunikation zwischen den Wedekind und dem Adressat
abgelaufen ist. Ebenso wird nach Standorten sortiert, um zu prüfen mit welchen Personen sich an den ...
\mytodos{Hier noch mehr INfos dazu, für was genau die Editoren diese tun}
Da die Daten in der 3. Normalform in der Datenbank gespeichert werden, sind einige Relationen für die Abfragen
notwendig. Dies wird durch die generische Abfrage in \autoref{lst:documentlist} gezeigt. Zusätzlich wird für jedes
dargestellte Dokument eine zusätzliche Abfrage durchgeführt, die in \autoref{lst:documentlist_sub} zeigt, dass auch hier
weitere Relationen notwendig sind.
\includecode[SQL]{chapters/thesis/chapter03_documentlist.sql}{lst:documentlist}{Generische Abfrage der Dokumentenliste}
\includecode[SQL]{chapters/thesis/chapter03_documentlist_sub.sql}{lst:documentlist_sub}{Sub-Abfrage pro Dokument}
Nach aktuellem Stand beinhaltet die Datenbank ca. 5400 Briefe, für die jeweils 2-7 eingescannte Faksimile gespeichert
werden. Diese Graphik-Dateien werden im TIFF-Format abgespeichert und benötigen zwischen 1 und 80 MB Speicherplatz.
Dadurch kommt die Datenbank aktuell auf ca. 3,8 GB.
\mytodos{Die unteren Punkte nochmal untergliedern in Performance-messen und Statistiken prüfen, dann kann mit den
Performance-messen die unterschiedlichen Aktionen durchgeführt werden in Kapitel 4}
Wie im Kapitel \ref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Die
PostgreSQL"=Schicht wurde schon im vorherigen Kapitel betrachtet. Daher gehen wir nun weiter nach oben in den Schichten
vom Glassfish"=Server.
Die OpenJPA Cache Schicht wird nun einzeln untersucht. Hierfür werden die zuerst die Cache"=Statistik für Object"=Cache
und Query"=Cache aktiviert \citep[315]{MüllerWehr2012}. Die somit erfassten Werte, werden über eine Webseite
bereitgestellt, um die Daten Live vom Server verfolgen zu können. Zusätzlich können diese Daten über ein Skript
zyklisch abgefragt, gespeichert und vergleichen werden.
In der \ac{JPA} Schicht sind die Anzahl der Entitäten im Persistence Context zu beobachten. Die Anzahl der verschiedenen
Klassen soll ermittelt und die Statistik"=Webseite um diese Daten erweitern. Um die Daten zu ermitteln, kann der
Quellcode aus \ref{lst:persistence-context-statistics} verwendet werden.
\begin{lstlisting}[language=Java,caption={Persistence"=Kontext Statistik},label=lst:persistence-context-statistics]
EntityManagerFactory emf = Persistence.createEntityManagerFactory(...);
EntityManager em = emf.createEntityManager();
for(EntityType<?> entityType : em.getMetaModel().getEntities())
{
Class<?> managedClass = entityType.getBindableJavaType();
System.out.println("Managing type: " + managedClass.getCanonicalName());
}
// Oder bei JPA 2.0
emf.getCache().print();
\end{lstlisting}
% \mytodos{\url{https://eclipse.dev/eclipselink/api/2.1/org/eclipse/persistence/jpa/JpaCache.html#getObject(java.lang.Class,%20java.lang.Object)}}
Die Schicht \ac{EJB} besitzt keine Möglichkeit um eine sinnvolle Messung durchzuführen, daher wird hierfür keine
direkte Messungen eingefügt.
Bei den \ac{JSF} wird eine Zeitmessung eingefügt. Hierfür müssen die Seiten so erweitert werden, dass zum einen die
Zeit gemessen wird um die Daten zu ermitteln. Zum anderen wird die Zeit gemessen wie lange es dann noch dauert um die
Seite mit den Daten zu rendern um diese an den Client auszuliefern. Diese 2 Zeiten sollen dann im Footer direkt auf der
Seite mit dargestellt werden. Somit kann der Benutzer auch direkt sehen, wenn das laden länger gedauert hat, an welcher
Stelle die Verzögerung aufgetreten ist.
Zum Schluss soll die gesamte Anwendung noch automatisiert getestet werden. Hierfür wird ein Shell-Skript erstellt, dass
automatisiert alle URLs der Webseite mehrfach abfragt. Die Dauer der Aufrufe der Webseiten werden gemessen und
statistisch ausgewertet. Für einen späteren Vergleich werden diese Informationen gesichert und mit einem erneuten Aufruf
nach den Optimierungen verglichen. Hierdurch kann auch festgestellt werden, ob die Optimierungen erfolgreich waren.
Um die Netzwerklatenz ignorieren zu können, wird das Skript auf dem gleichen Computer aufgerufen, auf dem die Webseite
gestartet wurde.
Das zugehörige Script ist im Anhang \ref{ap:timing} angehängt.
\section{Vergleich mit anderen Technologien}
\label{sec:concept:technologiecompare}
\mytodos{Noch tiefer eingehen?}
Damit eine Umsetzung auf eine andere Technologie umgestellt werden kann, muss dies den kompletten Technologie"=Stack
besitzen, wie dies von der \ac{JSF} unterstützt wird. Daher fallen reine FrontEnd"=Bibliotheken wie VueJS oder React aus
der Betrachtung heraus, da sie zusätzlich noch einen Backend für die Anwendungslogik (englisch business logic) benötigt.
\subsection{C\# - ASP.NET Core MVC}
\label{sec:concept:technologiecompare:aspnetcore}
Beim Vergleich zu \ac{JSF} steht ASP.NET Core MVC in nichts nach. Im großen und ganzen ist der Funktionsumfang der
gleiche und mit dem EntityFramework gibt es ebenfalls einen sehr mächtigen \ac{ORM}. Hierbei wird die Programmierung anhand
des \ac{MVC}"=Entwurfsmuster implementiert \citep{AspNetCore:2024:MVC}. Dieses Muster erleichtert die Trennung der
Benutzeranforderungen, welche durch die Controller mithilfe der Modelle abgearbeitet werden, von der Bedienoberfläche,
die hier in der Standardelementen von Webseiten, wie \ac{HTML}, \ac{CSS} und Javascript definiert werden. Zusätzlich
existiert noch ein spezifischer Syntax um die Daten dynamisch in die Seiten einzufügen.
Das System selbst ist in Schichten, auch Middleware genannt, aufgebaut \citep{AspNetCore:2024:Middleware}. Hierbei
übernimmt jede Middleware ihre entsprechende Aufgabe oder gibt die Anfrage an die nächste Middleware weiter und wartet
auf deren Antwort um diese und den Client zurückzugeben.
Diese Konzept wird direkt vom Standard umgesetzt und somit sind die unterschiedlichen Verarbeitungen getrennt
implementiert worden, was zu besserer Wartbarkeit des Programmcodes führt. Und die eigene Anwendung kann dadurch
je nach Bedarf die Middleware aktivierten, die wirklich benötigt wird.
Zusätzlich können über eine Vielzahl an vorhandenen NuGet-Paketen das Programm erweitert werden. Oder Komponenten
komplett ersetzt werden, wie z.B. das EntityFramework durch eine einfachere leichtere Version eines reinen \ac{ORM}
zu ersetzt.
C\# ist wie Java durch die neue .NET Runtime, aktuell in der Version 8 verfügbar, für die meisten Betriebssystem verfügbar.
Bei der Übersetzung hat C\# einen Vorteil gegenüber von Java, da hier der Code wie bei Java zuerst in eine Zwischencode
\ac{IL} kompiliert wird und zur Laufzeit über einen \ac{JIT} Compiler dann direkt in optimierten Maschinencode übersetzt wird.
Hierbei haben die meistens Test gezeigt, dass das .NET Framework hier um einiges effizienter und schneller arbeitet als
die Java Runtime. Zusätzlich wird bei ASP.NET Core nicht noch ein zusätzlicher Server benötigt um die Anwendung aktiv
zu halten.
\subsection{Golang}
\label{sec:concept:technologiecompare:golang}
Go (auch Golang) ist eine junge Programmiersprache, die sich durch Simplizität und Multifunktionalität auszeichnet, was
eines der Ziele bei der Entwicklung ist. Weitere Ziele waren die native Unterstützung von Nebenläufigkeit und die
leichte Verwaltung von großen Codebasen in größeren Entwicklerteams und ein hohen Übersetzungsgeschwindigkeit.
Hierdurch ist es sehr einfach und effizient möglich eine Anwendung mit Go zu entwickeln \citep{Golang:2024}.
Zusätzliche überzeugt Go durch die Typsicherheit und die automatische Speicherbereinigung durch den \ac{GC}.
Die Entwicklung von Microservices mit Go wird durch die integrierten Funktionen und Bibliotheken gut Unterstützt,
wodurch die Entwicklung, Bereitstellung und Skalierung erleichtert wird.
Go wird in eine native Anwendung übersetzt, da für die großen Betriebssystem entsprechende Compiler existieren, sind
Anwendung in Go ebenfalls nahezu Plattformunabhängig. Durch den integrierten Cross-Compiler, kann die Software direkt
für andere Betriebssystem mit erstellte werden.
Für eine dynamische Webseite, reichen die Standard-Bibliotheken, wobei auch hier gibt es verschiedene Frameworks die
eine Unterstützung für \ac{MVC} einbauen. Ein direkter \ac{ORM} ist ebenfalls vorhanden, um den einfachen Zugriff
auf eine Datenbank zu ermöglichen.
\subsection{PHP}
\label{sec:concept:technologiecmopare:php}
Mit der Skriptsprache PHP ist es sehr einfach eine dynamische Webseite zu entwickeln, da diese genau für solche
Zwecke entwickelt wurde. Hierbei wird der Code nicht übersetzt, sondern immer zu Laufzeit interpretiert, was im
Gegensatz zu den anderen vorgestellten Möglichkeiten im Sinne der Performance eindeutig ein Nachteil ist.
Dafür ist eine Änderung nur mit Hilfe eines Texteditor sehr einfach und schnell umzusetzen.
Der Zugriff auf eine Datenbank, ist direkt mit integriert und muss nur durch die Bereitstellung der passenden Treiber
aktiviert werden.
Die Template-Funktion für die Webseite wird nicht direkt unterstützt, sonder hier muss zwingend eine externe Bibliothek
verwendet werden. Sonst entsteht sehr viel gleicher Code, der auf Dauer nicht mehr Wartbar bleibt.
Für PHP gibt es ebenfalls umfangreiche Frameworks für die \ac{MVC}"=Unterstützung, wie z.B. \textit{Laravel} oder
\textit{Symfony}. Um diese Webseiten aber nun wieder auf den Webserver betreiben zu können wird der \textit{composer}
benötigt, der den Quellcode zusammenpackt und für die Bereitstellung vorbereitet. Hierbei ist die Leichtigkeit der
Skriptsprache aber verloren gegangen.
\subsection{Fazit}
\label{sec:concept:technologiecompare:summary}
Den größten Vorteil würde man aktuell mit der Umsetzung in Go bekommen, da dies für seine Geschwindigkeit und einfach
bekannt und Entwickelt wurde. Zudem ist die Programmiersprache sehr jung und hat keine Altlasten mit dabei. Der
größte Nachteil darin ist aber, dass hierfür noch nicht so viele Entwickler existieren, die dann das Projekt
unterstützen können.
Meiner Einschätzung nach, wäre ein Umstieg im aktuellen Stadium nicht sehr sinnvoll, da zum einen der großteil der
Anforderung umgesetzt ist, und für jeden Änderung die Mitarbeiter sich erst in die neue Code-Basis einarbeiten müssten.
Bei Weiterentwicklungen durch Studenten, ist man mit Java im Vorteil, da dies an der Uni gelehrt wird.