© Excellent backgrounds/Shutterstock.com
Konfiguration, Service Discovery und Resilience

Baukasten für flexible und robuste Microservices


Microservices locken mit dem Versprechen, neue Funktionalitäten zielgerichteter und schneller in Produktion zu bringen. Die Herausforderung ist dabei, den Überblick zu behalten. Denn wo früher noch die Verwaltung und Problemanalyse von Hand möglich war, hilft jetzt nur noch vollständige Automatisierung. Wie gut, dass es dafür fertige Komponenten für Konfiguration, Service Discovery und Resilience gibt.

Das große Versprechen einer Microservices-Architektur ist es, dass Ideen zielgerichteter und schneller umgesetzt werden und in Produktion gehen können. Wo es früher nur wenige Releases pro Jahr gab, sollen es jetzt mehrere Releases pro Tag sein, die jeweils automatisch in einer Continuous-Delivery-Pipeline getestet werden. Dies gelingt nur, wenn statt eines großen Monolithen kleine Services zielgerichtet in Produktion gebracht werden.

In einer solchen Umgebung ist die manuelle Konfiguration von Services genauso wenig möglich wie die manuelle Installation. Es sind Lösungen gefragt, die die dynamische Rekonfiguration der Services zulassen und dafür an zentraler Stelle hochverfügbar und passend zur Umgebung die notwendigen Konfigurationen bereitstellen. Die Umgebungen sollen sowohl dynamisch horizontal skalieren als auch jederzeit neue Services integrieren können. Einen Load Balancer von Hand zu konfigurieren, scheidet hier aus. Auch wenn ein Load Balancer für den Zugriff von außen einen zentralen Einstiegspunkt bieten kann, sollen sich Services innerhalb der eigenen Infrastruktur direkt austauschen. So wird der Load Balancer nicht zum unnötigen Engpass. Hierfür ist Service Discovery gefragt.

Services sind von ihrer eigenen Datenbank und den Services in ihrer Umgebung abhängig. Ist eine dieser Abhängigkeiten nicht verfügbar oder zu langsam, so ist der Service nicht verfügbar und Fehler pflanzen sich fort. Dies gilt sowohl in klassischen als auch in Microservices-Architekturen. Damit nicht ein defekter Service die anderen blockiert, sind robuste Schnittstellen notwendig. Da Microservices-Architekturen durch kleiner geschnittene Systeme viel mehr Schnittstellen haben, gibt es hierfür fertige Bibliotheken, um dies zu lösen. Davon profitieren auch klassische Architekturen.

Dynamische Konfiguration zur Laufzeit

Das erste, was eine Anwendung bei ihrem Start benötigt, ist ihre Konfiguration. Konfiguration ist das, was sich in verschiedenen Staging-Umgebungen wie Entwicklung, Test und Produktion unterscheidet und was ohne Ausrollen einer neuen Softwareversion geändert werden soll. Der Rest ist Programmcode. Die gute Nachricht: Da durch die Continuous-Delivery-Pipeline mehrmals pro Tag Softwareänderungen in Produktion gegeben werden können, kann an den Stellen auf Konfiguration verzichtet werden, bei denen sie früher auf Vorrat oder auf Verdacht eingebaut wurde. Zusätzlich kommen neue Konfigurationen hinzu, etwa für Feature Toggles, mit denen neue Funktionen erst in der Testumgebung, später in Produktion nach und nach für Nutzer freigegeben werden.

Der Klassiker für die Konfiguration von Java-Anwendungen ist die Apache-Commons-Configuration-Bibliothek [2]. Diese Bibliothek existiert seit über zehn Jahren und hat ein praxiserprobtes API. Die Daten kann die Bibliothek aus verschiedenen Quellen laden, angefangen von einer einfachen Properties-Datei bis hin zu einer JDBC-Datenquelle oder System Properties. Verschiedene Datenquellen lassen sich miteinander kombinieren, sodass eine Standardkonfiguration, die als Datei mit der Anwendung ausgeliefert wird, mit den umgebungsspezifischen Werten aus System Properties oder einer JDBC-Datenquelle überschrieben werden kann. Die Funktionen von Commons Configuration hat Netflix mit der Archiaus-Bibliothek [3] noch einmal erweitert. Das API blieb gleich, es kamen jedoch Konfigurationsänderungen zur Laufzeit und weitere Datenquellen wie Apache Zookeeper, Amazon DynamoDB und S3 dazu. Auf diese Weise lassen sich Einstellungen über verschiedene Cluster-Instanzen hinweg zur Laufzeit ändern, ohne dass ein Neustart notwendig ist.

Listing 1 zeigt den Aufruf einer Java-Anwendung mit zusätzlichen Kommandozeilenparametern. In diesem Fall werden verschiedene Konfigurationsdateien, seien es lokale Dateien oder URLs, auf der Kommandozeile übergeben. Weitere Parameter legen fest, wann das erste Mal die Konfiguration von den URLs (hier: nach einer Sekunde) und wie oft anschließend die Konfiguration neu geladen werden soll (hier: jede Sekunde).

Listing 1: Start der Anwendung mit Archaius-­Parametern

# Command Line Java with Archaius Parameters $ java -Darchaius.configurationSource.additionalUrls=file:///.../archaius.properties -Darchaius.fixedDelayPollingScheduler.delayMills=1000 -Darchaius.fixedDelayPollingScheduler.initialDelayMills=1000 –jar application.jar # archaius.properties app.timeout=1000

Listing 2 zeigt die Verwendung. Zunächst wird eine Objektinstanz vom Typ DynamicIntProperty instanziiert. Diese liest den Konfigurationswert app.timeout aus der Konfiguration. Ist er nicht gesetzt, gilt der im Code übergebene Standardwert von 10. Mit der Objektinstanz kann jederzeit auf den aktuellen Wert aus der Konfiguration zugegriffen werden. Da die Werte aus verschiedenen Datenquellen bereits im Hintergrund von Archaius zusammengeführt werden, geschieht der Zugriff innerhalb der virtuellen Maschine und ist damit lokal und schnell.

An vielen Stellen genügt es, mit get() den aktuellen Wert auszulesen. Manchmal muss jedoch in dem Moment, in dem sich die Konfiguration ändert, eine Aktion ausgeführt werden. Hierfür kann die Anwendung für jeden Konfigurationseintrag einen Callback registrieren, der immer dann aufgerufen wird, wenn sich der Wert geändert hat. Damit können auch komplexe Rekonfigurationen, zum Beispiel von Caches oder Thread...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang