Die Implementierung von Applikations–Architekturen hat sich in den letzten Jahren stark gewandelt. Vor wenigen Jahren dominierten noch monolithische Applikations–Architekturen mit dem Ziel, möglichst viel Code wiederzuverwenden. Das heutige Bild einer Applikations–Architektur sieht deutlich differenzierter aus und bietet uns neue Möglichkeiten.
Der Monolith
Viele Anwendungen wurden in der Vergangenheit mittels einer monolithischen Architektur umgesetzt. Ab einer gewissen Größe oder einem gewissen Alter wird es allerdings zunehmend schwerer, solche Anwendungen zu warten, zu erweitern oder gar zu modernisieren.
Dies resultiert aus einer meist sehr starken Bindung der einzelnen Komponenten an diesen Monolithen oder gar anderen technischen Beschränkungen, die es nicht erlauben, einen Teil der Anwendung zu modernisieren. Selbst kleinste Eingriffe, wie beispielsweise die Erneuerung einer Bibliothek, ist oftmals nicht ohne Nebeneffekt in anderen Teilen der Anwendung zu generieren. Genau diese Problematik stellte neue Anforderungen an zukünftige Applikations-Architekturen.
Auf diese neuen, gestiegenen Anforderungen reagieren wir mit der Implementierung von MicroServices beziehungsweise der Trennung des Core-Systems (Monolith) und den neuen Funktionalitäten.
Der MicroService
Aufgrund der steigenden Anforderungen bezüglich Skalierbarkeit und Geschwindigkeit in den Technologien, hinsichtlich des Erscheinens und wieder Verschwindens, werden heute immer mehr Applikationen mittels eines Netzes von lose gekoppelten (Micro-)Services implementiert. Die Verfügbarkeit von günstigen Cloud–Ressourcen und die allgemeine Akzeptanz von Container-Techniken wie LXC, Docker und Rkt begünstigen diese Entwicklung ebenfalls.
Denn bei diesen Services steht nicht mehr die Wiederverwendung von Code im Vordergrund, sondern die Wiederverwendung von Infrastruktur-Komponenten. Diese können ebenfalls durch allgemein verfügbare (Micro-)Services repräsentiert werden.
Um solche modularen Applikationen schnell und mit einer hohen Qualität zu erstellen, haben wir eine Toolbox entwickelt, welche häufig benötigte Services enthält und bündelt. Sie definiert damit eine grobe Applikations-Architektur auf Basis von MicroServices sowie Docker, Kubernetes und OpenShift.
MicroService Toolbox
Unsere MicroService Toolbox besteht unter anderem aus wiederverwendbaren Infrastruktur–Komponenten, wie zum Beispiel einem Templating–Service, der E-Mails oder Formulare rendert; einem Mail-Service, der E-Mails an eine SMTP–Queue übergibt und ein Protokoll fortschreibt. Die Komponenten wurden entweder von entsprechenden Projekten direkt übernommen oder erweitert. Dabei erfolgt die Übernahme immer als Quell-Artefakt um auf etwaige Änderungen in den Anforderungen direkt reagieren zu können.
Zudem beinhaltet unsere Toolbox auch abstrakte Artefakte, wie „Legacy“-Systeme oder Monolithen, welche als Core-System angebunden werden können. Dazu zählt beispielsweise auch die Anbindung von SAP-Systemen als System of Records mittels ODATA.
Für die Kommunikation zwischen den Services verwenden wir einen Message Broker. Dadurch erreichen wir eine echte asynchrone Kommunikation der Services untereinander und können bei Bedarf ein reliables Messaging aktivieren. Durch die „Stateless“ Auslegung unserer Services optimieren wir unsere MicroService Toolbox, da sich somit jeder Service beliebig skalieren lässt. Die Architektur der Toolbox ist konsequent auf die Erstellung von Cloud-Native beziehungsweise Container–Native Applikationen ausgelegt.
Container–Application
Wir verfolgten bei unserer Architektur einen Cloud–Native Ansatz mittels Container, so dass wir nahezu unabhängig vom Cloud–Anbieter unsere Toolbox nutzen können. So lässt sich unsere Toolbox sowie die darauf aufbauende Applikation zu jeder Zeit nahezu frei skalieren, überwachen und verteilen. Dadurch sind ebenfalls Multi–Cloud sowie Hybrid Szenarien denkbar. Durch diese Ausrichtung sind die von uns erstellen Applikationen zudem völlig von der darunter liegenden Infrastruktur gelöst. Für die Anwendung ist es somit nicht mehr von Bedeutung, wenn ein Betriebssystem–Update eine Bibliothek ändert, da diese Bibliothek im Container-Image immer die gleiche bleibt.
So auch beim Skalieren der Anwendung. Bisher waren aufwändige LoadBalancer–Konfigurationen notwendig. Diese Aufgaben erledigt jetzt die Container–Runtime.
Die Nutzung von Containern begünstigt zudem den Einsatz von Continuous Delivery oder Continuous Deployment Ansätzen, da der Container innerhalb von Sekunden fertig konfiguriert zur Verfügung steht. Sind diese Hürden erstmal genommen und die Anwendung im Container verpackt, ist der Schritt zu einem generellen DevOps–Ansatz nicht mehr groß. Mehr dazu in einem der nächsten Artikel.
von Thorsten Gawantka