Die Basis von Discoveroo, die Daten, sind in einer MySQL-Datenbank gespeichert. Diese enthält sechs Tabellen:
1. city_data
2. country_data
3. region_data
4. weather_data
5. currency_data
6. language_data
Für die Recommendation Engine werden city_data, country_data und weather_data benötigt.
Die Discoveroo REST API haben wir mit dem auf JavaScript basierenden Express.js Framework entwickelt. Die Endpunkte haben wir in vier Gruppen unterteilt:
1. Stadtrouten
2. Regionsrouten
3. Landrouten
4. Recommendation Engine
Dabei liegt der Fokus ganz klar auf der Recommendation Engine.
Für die Entwicklung des beispielhaften Frontend wurde das Framework Bootstrap verwendet. Das Frontend besteht aus Auswahl- und Ergebnisseite. Die Ergebnisseite ist dabei aus mehreren Karten aufgebaut, die jeweils Informationen zu einer empfohlenen Stadt visualisieren.
Was?
Das API Gateway ermöglicht und vereinfacht das Veröffentlichen, Warten, Überwachen und Sichern von APIs. Es stellt den zentralen Knotenpunkt zwischen anderen angebotenen AWS Services dar.
Warum?
Die Nutzung trägt nicht nur zur Komplexitätsreduktion bei, sondern ermöglicht auch die Entkopplung von Client und Backend. Außerdem werden die Latenz minimiert und automatisch Sicherheitsfeatures implementiert.
Wofür?
Wir nutzen diesen Service zum Erstellen von Development- und Produktionsstage, zum Deployen und Verwalten der API und zur Zugriffsverwaltung.
Was?
AWS Lambda ist ein Datenverarbeitungsservice, der es ermöglicht, Code auszuführen, ohne Server bereitstellen oder verwalten zu müssen. Der Code wird ausschließlich bei Bedarf ausgeführt und automatisch skaliert.
Warum?
Da wir nur für die tatsächliche Verarbeitungszeit bezahlen, können wir Kosten minimieren. AWS Lambda bietet hohe Verfügbarkeit, schnelle und flexible Bereitstellung und einfache Codeverwaltung.
Wofür?
Das gesamte Backend unserer Discoveroo API läuft in AWS Lambda. Es wird alles übernommen, was zum Ausführen und Skalieren des Codes für hohe Verfügbarkeit erforderlich ist. Einzelne Softwarebestandteile werden nur dann aufgerufen, wenn der entsprechende API-Endpunkt aufgerufen wird.
Was?
Amazon Relational Database Service (RDS) ist ein vollständig durch AWS verwalteter SQL-Datenbankservice, der eine Reihe von Optionen für Datenbank-Engines bietet, um Datenbankmanagement, Migration, Backup, Recovery und Patching zu unterstützen.
Warum?
Mit dem von AWS angebotenen Pay-as-you-go-Modell für RDS zahlen wir nur für tatsächlich genutzte Speicherkapazitäten. Außerdem werden uns das aufwändige Einrichten der Datenbank und zeitaufwendige Verwaltungsaufgaben abgenommen, Backups automatisiert vorgenommen und hohe Sicherheitsstandards ermöglicht.
Durch die Nutzung von Amazon RDS können wir eine Verfügbarkeit von 99,95% garantieren.
Wozu?
Wir nutzen MySQL 5.7, um unsere finalen csv-Dateien in einer relationalen Datenbank zu speichern. Mit Hilfe des angebotenen Monitorings können wir Daten über unsere Leistung gewinnen.
Was?
Amazon Simple Storage Service (Amazon S3) ist ein Objektspeicherservice, der es ermöglicht, beliebige Mengen an Daten zu speichern und zu sichern.
Warum?
Amazon S3 ist auf eine fast 100%ige Haltbarkeit ausgelegt und speichert Daten sicher und hoch verfügbar.
Wozu?
Die Stadtbilder haben wir in S3 Buckets gespeichert. Wir können diese dann über eine URL abrufen. Da es sich lediglich um Stadtbilder handelt, die wir selbst zuvor über eine Suchmaschine im Internet gesammelt haben, sind keine Zugriffsbeschränkungen notwendig. Daher sind die Bilder - für jeden mit Kenntnis über die URL - öffentlich zugänglich. Es handelt sich um 2419 Bilder.
Wählen Sie aus einer großen Auswahl der jüngsten voreingestellten Blocks - Full Screen Intro, Bootstrap Slider, Content Slider, responsive Bildergalerie mit der Lightbox, Parallax Scrolling, Video Hintergründe, mobiles Menü sowie noch viele weitere Dinge.
Wählen Sie aus einer großen Auswahl der jüngsten voreingestellten Blocks - Full Screen Intro, Bootstrap Slider, Content Slider, responsive Bildergalerie mit der Lightbox, Parallax Scrolling, Video Hintergründe, mobiles Menü sowie noch viele weitere Dinge.
Alle Websites, die mit Mobirise gebaut werden, sind mobil-freundlich und Sie müssen gar nichts dafür tun. Sie müssen auch keine mobile Version für Ihre Site zusätzlich bauen, denn sie wird sich jedem Bildschirm automagisch anpassen.
Alle Websites, die mit Mobirise gebaut werden, sind mobil-freundlich und Sie müssen gar nichts dafür tun. Sie müssen auch keine mobile Version für Ihre Site zusätzlich bauen, denn sie wird sich jedem Bildschirm automagisch anpassen.
Verkürzen Sie die Zeit der Seitenentwicklung mit dem Drag-and-Drop Website Baukasten. Ziehen Sie Blocks auf Ihre Seite, bearbeiten Sie den Inhalt und veröffentlichen Sie Ihre Website – da braucht keine technischen Fähigkeiten.
Verkürzen Sie die Zeit der Seitenentwicklung mit dem Drag-and-Drop Website Baukasten. Ziehen Sie Blocks auf Ihre Seite, bearbeiten Sie den Inhalt und veröffentlichen Sie Ihre Website – da braucht keine technischen Fähigkeiten.
Wählen Sie aus einer großen Auswahl der jüngsten voreingestellten Blocks - Full Screen Intro, Bootstrap Slider, Content Slider, responsive Bildergalerie mit der Lightbox, Parallax Scrolling, Video Hintergründe, mobiles Menü sowie noch viele weitere Dinge.
Wählen Sie aus einer großen Auswahl der jüngsten voreingestellten Blocks - Full Screen Intro, Bootstrap Slider, Content Slider, responsive Bildergalerie mit der Lightbox, Parallax Scrolling, Video Hintergründe, mobiles Menü sowie noch viele weitere Dinge.
Das Dashboard zeigt Aufruf- und Errorstatistiken. Die Auswertungen der Errorstatistiken helfen dabei, auftretende Fehler zu untersuchen. Der zeitliche Verlauf der Datenbanklast wird genutzt, um mögliche Engpässe zu identifizieren. Gemessen und visualisiert wird außerdem die Latenz. AWS CloudWatch ermöglicht uns neben Nutzungs- und Fehleranalysen auch proaktive Ressourcenoptimierung. Dazu können Alarme erstellt werden. Wenn ein Alarm ausgelöst wird, können von CloudWatch automatisch bestimmte Maßnahmen ergriffen werden.
Die Lasttests werden mit dem Python-basierten Open-Source-Programm Locust durchgeführt. Bei jeder Anfrage wird zufällig eine URL generiert, um zu vermeiden, dass alle abgefragten Daten aus dem Cache gelesen werden. Alle drei bis vier Sekunden führt ein Nutzer einen Request durch. Daraus folgt, dass die Anzahl der Aufrufe pro Sekunde gringer als die Anzahl der Nutzer ist. Es werden Tests mit 100, 200, 300, 400, 500 und 600 Nutzern durchgeführt.
Ab 600 Nutzern treten vermehrt Fehler auf. Die Response Time bleibt gleich. Die Anzahl gleichzeitiger Datenverbindungen bei der verwendeten AWS RDS Instanz ist auf 65 begrenzt. Daher kann davon ausgegangen werden, dass primär die Anzahl der Datenbankverbindungen der Bottleneck ist.
Wir haben die API durch das Senden verschiedener URLs via unserem selbstentwickelten Frontend auf Fehlerfreiheit und Sinnhaftigkeit überprüft. Dabei haben wir verschiedene Eingabekombinationen ausprobiert und diese ebenso wie die Ergebnisse und eventuelle Auffälligkeiten notiert. Die manuellen Tests haben uns geholfen, Leichtsinns-, Syntax- und Logikfehler im Programmcode zu entdecken. Diese konnte wir im Anschluss beheben. Wir konnten außerdem feststellen, dass sich die Anzahl der Ergebnisse je nach Eingabeparametern stark unterscheidet. Die manuelle Verifizierung hat uns daher geholfen, die Stärken und Schwächen unserer Datenbasis herauszukristallisieren.
+ Geeignet für komplexe Abfragen
- Teure Skalierung
- Einheitliche Datenstruktur notwendig
- Ggf. viele NULL-Werte (wenn Parameter nicht für alle Städte/Regionen/Länder verfügbar)
+ Gute Skalierbarkeit durch einfachen Aufbau
+ Schemaänderung während Betrieb möglich
- Eingeschränkte Abfragemöglichkeiten
- Ungeeignet für komplexe Objekt- Beziehungsmodelle
Anwendung: Hochverfügbare Anwendungen, bei denen Daten anhand eines Schlüssels mittels einfacher Abfragen schnell abgerufen werden sollen.
+ Sehr gute Skalierbarkeit
+ Hohe Lesegeschwindigkeit bei Abfragen einer oder weniger Zeilen
- Niedrige Lesegeschwindigkeit bei Abfragen über viele
Anwendung: Analytische Informationssysteme mit simpel strukturierten, konsistenten Daten, bei denen eine unmittelbare Datenverarbeitung notwendig ist.
+ Flexible, komplexe Vernetzungen zwischen Daten möglich
+ Durch Graph-Struktur kann auf komplexe Abfragen verzichtet werden
- Viele Abfragesprachen und Graphmodelle
- Hohe Komplexität
Anwendung: Datenbanken, in denen die komplex verknüpften Datenbeziehungen eine große Rolle spielen.
Für unsere Datenbank ist neben optimierter Lesegeschwindigkeit vor allem wichtig, dass auch komplexe Abfragen in möglichst geringer Zeit bewältigt werden können. Aus diesem Grund nutzen wir SQL.
+ Unkomplizierte Arbeit mit Firewalls und Proxies
+ Hohe transaktionale Zuverlässigkeit
+ Grundlegende Sicherheit gegeben
- Langsam (im Vergleich zu REST)
- Hohe Bandbreite (im Vergleich zu REST)
+ Kein Overfetching
+ Unterstützt verschiedene Frameworks (bspw. Angular, Node, React)
+ Ein einziges Schema zur Beschreibung der Daten
+ Daten können sehr genau ausgesucht werden
+ Verschiedene Ressourcen in einer Anfrage ausgebbar
- Ggf. komplexe Anfragen
- Schwierige Umsetzung von Rate Limiting
- Schwierige Umsetzung von Caching
- Schwieriges Error Handling
+ Einfache Erstellung
+ Einfache Integrierung
+ Hohe Skalierbarkeit durch zustandslose Kommunikation
+ Unabhängigkeit zwischen Server und Client
- Ggf. chaotisches URI Mapping bei großen Datenmengen
+ Unkomplizierte Arbeit mit Firewalls und Proxies
+ Hohe transaktionale Zuverlässigkeit
+ Grundlegende Sicherheit gegeben
- Langsam (im Vergleich zu REST)
- Hohe Bandbreite (im Vergleich zu REST)
Aufgrund der Einfachheit in der Umsetzung und der Konformität mit vielen Web-Diensten nutzen wir das - oft als Standard angesehene - REST-Programmierparadigma.
+ Einfach zu lernen
+ Hohe Performance (speziell im Vergleich zu Laravel und Django)
+ Grundlage: JavaScript (relativ einfache, uns bekannte Entwicklungssprache)
+ Grundlage: PHP
- Sehr schlechte Performance (im Vergleich zu Express.js)
+ Grundlage: Python (einfache, uns bekannte Entwicklungssprache)
- Schwierig zu lernen
- Schlechte Performance (im Vergleich zu Express.js)
- Grundlage: Ruby (uns unbekannte Entwicklungssprache)
- Langsamer als JavaScript
Das API Framework unserer Wahl ist Express.js, da es eine hohe Performance aufweist und sich auf die uns bekannte Entwicklungssprache JavaScript stützt. Auf Grund der zeitlichen Begrenzung des Projekts ist die Komplexität und Erlernbarkeit der Entwicklungssprache ein wichtiges Kriterium, um die von uns gesetzten Ziele erreichen zu können.