Kommunikation zwischen Front- und Backend

This commit is contained in:
2026-03-21 12:54:12 +01:00
parent 1c6ab71ada
commit 708c6a46a4

View File

@@ -2,19 +2,7 @@
# Konstantin Hintermayer # Konstantin Hintermayer
## Einleitung des individuellen Teils ## Einleitung
In diesem Abschnitt wird meine persönliche Aufgabenstellung im Rahmen des Projektes (`Alumnihub`) beschrieben.
### Auftrag / persönliche Aufgabenstellungen
Meine Zuständigkeiten und Verantwortlichkeiten:
- Product Owner
- Infrastruktur
- Entwicklung
- Auswertungen
- Schwarzes Brett
### Motivation ### Motivation
@@ -22,6 +10,39 @@ Gegenstand der Diplomarbeit ist die Entwicklung modularer Webanwendungen mit Bla
Mein Untersuchungsanliegen: Inwieweit optimiert die Integration von Blazor und dem Oqtane-Framework die Konsistenz und Wartbarkeit modularer Web-Architekturen im Vergleich zu den für mich gewohnten Technologie-Stacks (React/Node.js)? Mein Untersuchungsanliegen: Inwieweit optimiert die Integration von Blazor und dem Oqtane-Framework die Konsistenz und Wartbarkeit modularer Web-Architekturen im Vergleich zu den für mich gewohnten Technologie-Stacks (React/Node.js)?
### Auftrag und persönliche Aufgabenstellungen
Mein Aufgabenbereich in diesem Projekt war vielseitig und umfasste sowohl leitende als auch tiefgreifende technische Aspekte. Die Rollen lassen sich in drei Kerngebiete unterteilen:
#### Projektleitung und Organisation (Product Owner)
\
Als Product Owner war ich für die Definition der Produktvision und die Priorisierung des Backlogs verantwortlich. Dies beinhaltete:
- **Anforderungsmanagement**: Erhebung und Strukturierung der Anforderungen in Zusammenarbeit mit den Betreuern und dem Team.
- **Sprint-Planung**: Organisation der 14-tägigen Sprints in YouTrack, um einen kontinuierlichen Entwicklungsfluss sicherzustellen.
- **Qualitätssicherung**: Definition der *Definition of Done* (DoD) und Durchführung von Code-Reviews zur Einhaltung von Architekturstandards.
#### Infrastruktur und Systemarchitektur
\
Ein wesentlicher Teil meiner Arbeit lag in der Bereitstellung der technischen Basis für das gesamte Team:
- **Deployment-Strategie**: Konzeption und Umsetzung der Server-Infrastruktur auf Basis von Debian Linux und NginX als Reverse-Proxy.
- **Datenbankdesign**: Entwurf des relationalen Datenmodells in PostgreSQL, inklusive der Absicherung durch SSL/TLS.
- **CI/CD-Pipeline**: Automatisierung der Build- und Deployment-Prozesse mittels Gitea Actions für eine effiziente Integration der Teambeiträge.
#### Modulentwicklung
\
Zusätzlich zur Infrastruktur habe ich drei zentrale Module für den Alumnihub entworfen und implementiert:
1. **Anmeldetool (EventRegistration)**: Ein Modul zum verwalten von Anmeldungen für Veranstaltungen. Es ermöglicht die einfache Erstellung von Einladungen zu Veranstaltungen und die Verwaltung von Anmeldungen.
2. **Reporting System**: Ein generisches System zur Meldung von Inhalten, das nach dem *Open-Closed-Prinzip* entworfen wurde, um eine einfache Erweiterbarkeit für alle anderen Module zu bieten.
3. **Schwarzes Brett (BlackBoard)**: Ein Community-Modul für den Austausch von Informationen, inklusive eines automatisierten E-Mail-Digest-Systems zur Nutzerbenachrichtigung.
## Anforderungen an das entwickelte Modul bzw. die Funktionalität ## Anforderungen an das entwickelte Modul bzw. die Funktionalität
### Modulanforderungen / funktionale Anforderungen ### Modulanforderungen / funktionale Anforderungen
@@ -88,21 +109,55 @@ Ein Modul in Oqtane besteht aus vier Projekten:
### Zusammenspiel der Infrastruktur ### Zusammenspiel der Infrastruktur
In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen. Wir verwenden NginX als Reverse Proxy, welcher bei uns die SSL Terminierung macht. Das Zertifikat, welches verwendet wird, wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert und verwaltet. Oqtane selber läuft als Systemd-Service im Kestrel Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback IP und Port 5000. Damit ist Oqtane nur durch NginX erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback IP und Port 5432. In der folgenden Grafik ist das System Schematisch dargestellt. In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen.
#### NginX as Reverse Proxy
NginX fungiert in unserer Infrastruktur als `Reverse Proxy`. Ein Reverse Proxy nimmt Anfragen aus dem Internet entgegen und leitet sie an interne Server (wie Kestrel) weiter. Dies bietet mehrere Vorteile:
- **Sicherheit**: Die interne Applikation ist nicht direkt dem Internet ausgesetzt.
- **SSL-Terminierung**: NginX übernimmt die rechenintensive Verschlüsselung (HTTPS), während die Applikation dahinter über einfaches HTTP kommuniziert.
- **Statische Inhalte**: NginX kann statische Dateien (Bilder, CSS) effizienter ausliefern als ein Applikationsserver.
Wir verwenden NginX für die SSL Terminierung. Das Zertifikat wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert.
Hier ist ein Auszug der NginX-Konfiguration (`nginx.conf`) für den Alumnihub:
```nginx
server {
listen 443 ssl;
server_name alumni.example.com;
ssl_certificate /etc/letsencrypt/live/alumni.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/alumni.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
Oqtane selber läuft als Systemd-Service im Kestrel Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback IP und Port 5000. Damit ist Oqtane nur durch NginX erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback IP und Port 5432. In der folgenden Grafik ist das System Schematisch dargestellt.
```mermaid ```mermaid
architecture-beta sequenceDiagram
group server(server)[Server] participant browser as Client
participant nginx as NginX
participant oqtane as Oqtane
participant db as PostgreSQL
service db(database)[PostgreSQL] in server browser->>+nginx: HTTPS => 0.0.0.0:443
service oqtane(server)[Oqtane] in server nginx->>nginx: SSL Terminierung
service nginx(server)[NginX] in server nginx->>+oqtane: HTTP => 127.0.0.1:5000
oqtane->>+db: SQL => 127.0.0.1:5432
service internet(cloud)[Internet] db-->>-oqtane: SQL
oqtane-->>-nginx: HTTP
internet:R <--> L:nginx nginx-->>-browser: HTTPS
nginx:R <--> L:oqtane
oqtane:R <--> L:db
``` ```
Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Der SSH Service ist in jeder Umgebung anders erreichbar gewesen. Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Der SSH Service ist in jeder Umgebung anders erreichbar gewesen.
@@ -125,14 +180,19 @@ Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es möglich m
Blazor hat mehrere Hosting-Modelle: Blazor hat mehrere Hosting-Modelle:
- Blazor Web App: Hier wird die Web App als Teil einer ASP.NET Core Anwendung bereitgestellt. Dabei gibt es mehrere Render Modi: | Hosting-Modell | Ausführungsort | Interaktivität | Kommunikation |
- Static Server: Die Komponente wird serverseitig gerendert und besitzt keine Interaktivität. Es ist der standardmäßige `RenderMode` | :--- | :--- | :--- | :--- |
- Interactive Server: Die Komponente wird serverseitig gerendert, diesmal ist sie jedoch interaktiv. Das bedeutet, man kann mithilfe von C# den Zustand der Seite dynamisch bearbeiten. Diese Zustandsänderungen werden serverseitig bearbeitet. Hierbei kommunizieren Server und Client mithilfe von SignalR über WebSockets miteinander. | **Static Server** | Server | Keine | HTTP (Initialer Load) |
- Interactive WebAssembly: Die Komponente wird clientseitig, also im Browser, gerendert. Damit der Blazor C# Code auch im Browser ausgeführt werden kann, wird dieser in WebAssembly kompiliert. | **Interactive Server** | Server | Hoch (Echtzeit) | SignalR / WebSockets |
- Interactive Auto: Im `Interactive Auto` Modul wird bei dem initialen Besuch der Webseite der `Interactive Server` Modus gewählt und im Hintergrund wird der WebAssembly-Build heruntergeladen, damit bei weiteren Besuchen der Seite der `Interactive WebAssembly` Modus gewählt werden kann. | **Interactive WebAssembly** | Client (Browser) | Hoch (Lokal) | REST API / HTTP |
- Hybrid: Dieser Modus ist der Einzige, welcher nicht innerhalb einer Blazor Web App läuft, sondern in einem WebView in einer Nativen App. Dabei wird innerhalb des Mutterprozesses, ganz ohne WebServer, der C# und Razor-Code ausgeführt. Das Ganze funktioniert in WPF und WinForms Apps und in nativen mobilen Apps für Android und iOS mithilfe von .NET MAUI. | **Interactive Auto ** | Server & Client (ab zweitem Besuch) | Hoch (Echtzeit / Lokal) | SignalR / Websockets / RestAPI / HTTP |
| **Hybrid** | Native App (WebView) | Hoch (Lokal) | n/a (Mutterprozess) |
Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von inline C# beeinflusst werden kann. Das Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Datei liegen, oder in einer seperaten Code-Behind-Datei. Inline C# Code wird mithilfe von `@`- Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter: Table: Vergleich der Blazor Hosting-Modelle
Im Rahmen dieser Diplomarbeit haben wir und für den RenderModus Interactive Server entschieden. Dieser Modus ist für Oqtane die Standardeinstellung und bietet eine gute Balance zwischen Leistung und Benutzerfreundlichkeit. Das ist für unseren Anwendungsfall auch die Empfehlung von Oqtane selbst. [@oqtane_docs_rendermodes]
Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von inline C# beeinflusst werden kann. Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Datei liegen, oder in einer seperaten Code-Behind-Datei. Inline C# Code wird mithilfe von `@`- Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter:
```razor ```razor
<h1>Counter</h1> <h1>Counter</h1>
@@ -164,7 +224,30 @@ Razor hat auch eine Reihe an Keywords, wie zum Beispiel (nur Auszugsweise, bzw.
#### Kommunikation zwischen Front- und Backend #### Kommunikation zwischen Front- und Backend
Wie Front- und Backend miteinander interagieren hängt hauptsächlich vom Render-Modus ab. Oqtane kann auf verschiedene Arten betrieben werden. Hierbei ist es dem Modulentwickler ziemlich egal, welche Art der Kommunikation (WebSockets, HTTP Long-Polling, REST) verwendet wird. SignalR ist eine Library aus dem ASP.NET Framework, welche es möglich macht, Server zu Client Kommunikation zu betreiben. Oqtane verwendet SignalR im `Interactive Server (SignalR)` Render-Modus. Die Interaktion zwischen Client und Server folgt in Oqtane einem klaren Architekturmuster, das je nach Render-Modus unterschiedliche Technologien nutzt.
- **SignalR (Interactive Server)**: Für Echtzeit-Interaktionen nutzt Oqtane SignalR. Dabei wird eine persistente WebSocket-Verbindung (oder Fallbacks wie Long-Polling) aufgebaut. Zustandsänderungen im UI lösen C#-Events auf dem Server aus, und das resultierende "Diff" des DOMs wird zurück an den Client gestreamt.
- **REST API (WebAssembly/Shared)**: Bei Modulen, die Daten asynchron laden (im WebAssembly-Modus), kommuniziert der Client über einen `HttpClient` mit dem Controller.
Der folgende Ablauf zeigt die Kommunikation bei einer typischen Datenabfrage in einem Oqtane-Modul:
```mermaid
sequenceDiagram
%
participant C as Blazor Client (Razor)
participant S as Oqtane Server (Controller)
participant R as Repository (EntityFramework)
participant D as PostgreSQL
C->>+S: HTTP GET /api/[Module]/[Id]
S->>+R: GetEntity(Id)
R->>+D: SQL Query
D-->>-R: Data Result
R-->>-S: Entity Model
S-->>-C: JSON Response
```
Durch diese Abstraktion bleibt die Geschäftslogik im Backend (Repository/Controller) gekapselt, während das Frontend lediglich die Daten präsentiert und Benutzereingaben entgegennimmt. Dies unterstützt die Testbarkeit, da Repositories unabhängig vom UI getestet werden können.
### Dependency Injection ### Dependency Injection