iX 1/2018
S. 118
Praxis
JavaScript
Aufmacherbild

Microservices mit Node.js

Turbolader

Eine Applikation mit Microservices und Node.js umzusetzen, bietet sich häufig an. Schwerer fällt die Wahl zwischen dem synchronen und dem asynchronen Ansatz.

Auf jeder Konferenz finden sich mittlerweile Vorträge zum Thema Microservices, einige Veranstaltungen haben ihm gar ganze Tracks gewidmet: Microservice-Architekturen sind im Trend. Neben Java wenden sich immer mehr Programmierer JavaScript, genauer der Umsetzung mit Node.js zu. Der Ansatz ist attraktiv, denn den Kern ihrer Plattform halten die Entwickler seit vielen Jahre ausgesprochen klein, ausschließlich die wichtigsten Funktionen nehmen sie auf und schonen so wichtige Komponenten wie den Arbeitsspeicher.

Außerdem kann Node.js auf die größte Paketsammlung zurückgreifen. Der Node Package Manager (NPM) bietet für nahezu jede Situation ab Werk ein passendes Paket, das der Programmierer in eine Applikation einbinden kann. Hinzu kommt, dass sich Node.js auf allen gängigen Betriebssystemen installieren lässt und Adapter sowie Treiber zum Anbinden zum Beispiel von Datenbanken oder Message Queues umfasst. Dieser Artikel stellt im Rahmen einer Webanwendung zwei gänzlich unterschiedliche Microservices vor und geht auf ihre Umsetzung sowie ihre jeweiligen Vor- und Nachteile ein.

Entlastung durch Microservices

Ein zunehmender Funktionsumfang resultiert in komplexeren Applikationen, was die Wartung des bestehenden Quellcodes erschwert und die Integration neuer Funktionen verlangsamt und verteuert. Hier setzen Microservices an, denn mit ihnen lassen sich unterschiedliche Bereiche eines Programms voneinander entkoppeln.

Neben einer reduzierten Komplexität der einzelnen Komponenten kommen aber noch weitere Vorteile hinzu: Jeder Entwickler kann sich auf einen speziellen Microservice konzentrieren und zu einem Experten in seinem Bereich werden. Sind die Services erst einmal umgesetzt, lassen sie sich außerdem unabhängig voneinander skalieren. Das bedeutet, dass sich von einem besonders beanspruchten Service mehrere Instanzen hochfahren lassen, zwischen denen das System die Last verteilt. Andere Services laufen hingegen weiter wie gehabt.

Es ist jedoch nicht in jedem Fall sinnvoll, auf Microservices zu setzen. Ihre Einführung in einer Applikation stellt zunächst immer einen Mehraufwand dar, da man den Service auslagert und das Programm mit ihm kommunizieren muss. Das lohnt sich erst ab einer gewissen Komplexität einer Anwendung oder wenn man bestimmte Komponenten skalieren muss.

Zerlegt: Die NodeShop-Anwendung integriert einen synchronen und einen asynchronen Microservice (Abb. 1).

Was aber bedeutet eine Microservice-Architektur für die Applikation? Die Implementierung und die Auswirkungen von Microservices auf die Architektur lassen sich am besten an einem konkreten Beispiel zeigen. Im Zuge dieses Artikels dient ein einfacher Webshop auf Basis von Node.js als Vorführmodell. Abbildung 1 zeigt den Aufbau der Applikation.

Den Einstieg für die Nutzer stellt die eigentliche Anwendung namens NodeShop dar. Hierbei handelt es sich um eine Express-Applikation, deren Aufgaben das Ausliefern von Inhalten über HTTP und das Behandeln der Sessions der Anwender sind. Die Informationen über den Artikelkatalog bezieht das Programm vom Article-Service. Der eigentliche Einkauf und das Verwalten der Warenkörbe übernimmt der Checkout-Service.

Einstieg in die Applikation

Node.js kann in einer Anwendung sowohl in die Rolle eines Microservice selbst als auch in die Rolle eines Clients schlüpfen. Der Einstieg in die Applikation, also der NodeShop, ist ein Konsument der unterschiedlichen Microservices. Der Browser des Anwenders kontaktiert diesen Endpunkt, der die Anfragen wiederum an die zuständigen Services weiterleitet. Das geschieht aus einem guten Grund: Würde der Browser mit den Microservices einer Applikation direkt kommunizieren, müssten sie allgemeine Aufgaben wie Authentifizierung und Session Handling selbst übernehmen. Außerdem müsste der Entwickler die Services separat gegen Angriffe von außen absichern. Mit einem zentralen Einstieg kann er diese Dienste an genau einer Stelle des Programms zur Verfügung stellen, was die Komplexität und Fehleranfälligkeit reduziert. Auf Microservices basierende Applikationen setzen häufig auf solch ein als API-Gateway bezeichnetes Entwurfsmuster.

Eine zentrale Rolle spielt das API-Gateway, es stellt den Einstiegspunkt in eine Anwendung dar (Abb. 2).

Der grundsätzliche Aufbau der Applikation orientiert sich am Konzept Model View Controller (MVC), das Software in die drei Bereiche Datenmodell, Präsentation und Programmsteuerung einteilt. Den Einstieg für den Nutzer bildet der Router (siehe Abbildung 2). Er definiert die verfügbaren Kombinationen aus HTTP-Methode und URL-Pfad. An sie sind die Actions der Controller gebunden. Dabei handelt es sich lediglich um Callback-Funktionen, die eine bestimmte Signatur aufweisen müssen. Die Actions ihrerseits sorgen dafür, dass relevante Informationen aus der Anfrage extrahiert und den Models zur Verfügung gestellt werden. Die Models der Anwendung enthalten die Businesslogik und sind für die Datenhaltung verantwortlich.