Unser Hauptprodukt — ein Informationssystem für eine Versicherungsgesellschaft — war auf eine Größe angewachsen, die schnelles Deployment von Änderungen unmöglich machte. Ein einzelnes Deployment dauerte Stunden, und ein Bug im Abrechnungsmodul legte das gesamte System lahm. Wir beschlossen, den Monolithen in Microservices aufzuteilen. Hier sind unsere Erfahrungen aus den ersten Monaten.
Was ein Monolith ist und warum er nicht mehr ausreicht¶
Eine monolithische Anwendung ist ein einzelnes deploybares Artefakt — in unserem Fall eine WAR-Datei von über 400 MB Größe. Sie enthielt alles: Vertragsverwaltung, Abrechnung, Reporting, Benachrichtigungen und Importe aus externen Systemen. Jede Änderung erforderte das Bauen des gesamten Artefakts, Regressionstests liefen über Nacht, und Deployment bedeutete Downtime.
Das Entwicklungsteam wuchs — von fünf auf zwanzig Personen. Merge-Konflikte wurden zur Tagesroutine. Jeder Sprint endete in einer „Integration Hell” — drei Tage, in denen alle versuchten, ihre Änderungen in den Hauptbranch zu bekommen, ohne die Arbeit der Kollegen zu zerstören.
Microservices: Das Prinzip der einzelnen Verantwortung¶
Die Idee hinter Microservices ist einfach: Jeder Dienst macht eine Sache und macht sie gut. Er hat seine eigene Datenbank, seine eigene API, seinen eigenen Deployment-Zyklus. Er kommuniziert mit anderen über eine klar definierte Schnittstelle — typischerweise eine REST-API oder Messaging.
Im März 2014 veröffentlichten Martin Fowler und James Lewis den maßgeblichen Artikel über Microservices, der zusammenfasste, was Netflix, Amazon und Spotify seit Jahren praktizierten. Wir begannen mit einem kleineren Projekt zu experimentieren — dem Benachrichtigungssystem.
Erste Schritte: Extraktion des Benachrichtigungsdienstes¶
Das Benachrichtigungsmodul war ein idealer Kandidat für die Extraktion. Es hatte eine klare Schnittstelle (Ereignis empfangen → E-Mail/SMS senden), minimale Abhängigkeiten vom Rest des Systems und ein eigenes Datenmodell. Wir erstellten eine eigenständige Spring-Boot-Anwendung mit einem REST-Endpunkt:
@RestController
@RequestMapping("/api/v1/notifications")
public class NotificationController {
@Autowired
private NotificationService service;
@PostMapping
public ResponseEntity<Void> send(
@RequestBody NotificationRequest request) {
service.dispatch(request);
return ResponseEntity.accepted().build();
}
}
Statt eine Klasse direkt aufzurufen, sendete der Monolith nun einen HTTP POST an den Benachrichtigungsdienst. Wir fügten das Circuit-Breaker-Pattern hinzu (Netflixs Hystrix-Bibliothek) — wenn der Benachrichtigungsdienst nicht innerhalb von 2 Sekunden antwortete, fuhr das System ohne die Benachrichtigung fort und stellte sie in eine Retry-Warteschlange.
Herausforderungen, auf die wir gestoßen sind¶
Verteilte Transaktionen¶
Im Monolith reichte eine einzige Datenbanktransaktion. Über Dienste hinweg funktioniert dieser Ansatz nicht. Wir wechselten zu einem Eventual-Consistency-Modell — das System ist nicht sofort konsistent, konvergiert aber innerhalb kurzer Zeit. Für Geschäftsprozesse, die Atomarität erforderten, implementierten wir das Saga Pattern — eine Kette von kompensierenden Aktionen.
Service Discovery¶
Wo läuft der Benachrichtigungsdienst? Auf welchem Port? Fest einprogrammierte URLs in Konfigurationsdateien erwiesen sich schnell als Alptraum. Wir setzten Netflix Eureka als Service Registry ein — jeder Dienst registriert sich beim Start und andere fragen Eureka, wohin sie Anfragen senden sollen.
Monitoring und Logging¶
Im Monolith reichte eine Log-Datei. Mit Microservices haben wir Dutzende von Logs auf verschiedenen Servern. Wir führten zentralisiertes Logging über den ELK Stack (Elasticsearch, Logstash, Kibana) und eine Correlation ID ein — eine eindeutige Anfrage-Kennung, die durch alle Dienste wandert.
Testing¶
Unit-Tests blieben unkompliziert. Integrationstests wurden jedoch komplexer — man braucht laufende abhängige Dienste. Wir führten Consumer-Driven Contract Testing mit der Pact-Bibliothek ein: Jeder Dienst definiert einen Vertrag für seine API und Konsumenten validieren ihn in ihren eigenen Tests.
Technologie-Stack¶
- Spring Boot — schneller Start für einen neuen Dienst, Embedded Tomcat, Auto-Konfiguration
- Netflix OSS — Eureka (Discovery), Hystrix (Circuit Breaker), Ribbon (Load Balancing)
- RabbitMQ — asynchrones Messaging zwischen Diensten
- PostgreSQL — jeder Dienst hat sein eigenes Schema oder eine eigene Datenbank
- ELK Stack — zentralisiertes Logging und Monitoring
- Jenkins — CI/CD-Pipeline für jeden Dienst einzeln
Ergebnisse nach sechs Monaten¶
Wir extrahierten fünf Dienste aus dem Monolithen: Benachrichtigungen, Reporting, Datenimport, Authentifizierung und Dokumentenverwaltung. Das Deployment eines einzelnen Dienstes dauert Minuten statt Stunden. Das Team ist in Squads aufgeteilt — jedes Squad besitzt 1–2 Dienste End-to-End.
Die Deployment-Frequenz stieg von einem Deployment pro Monat auf mehrere pro Woche für jeden Dienst. Ein Bug im Reporting bedeutet nicht mehr, dass das gesamte System ausfällt — andere Dienste laufen weiter.
Wann Microservices keinen Sinn ergeben¶
Microservices sind keine Wunderwaffe. Für ein kleines Team (2–3 Entwickler) ist der Overhead enorm — man betreibt ein verteiltes System mit allem, was dazugehört. Wenn man keine klaren Grenzen zwischen Domänen hat, endet man mit einem „verteilten Monolithen” — dem Schlimmsten aus beiden Welten.
Unsere Empfehlung: Starten Sie mit einem Monolithen, aber mit einer sauberen modularen Struktur. Wenn Sie den Schmerz spüren — langsame Deployments, organisatorische Reibung, die Notwendigkeit, nur einen Teil des Systems zu skalieren — dann extrahieren Sie.
Microservices sind eine organisatorische und technische Veränderung¶
Der Übergang zu Microservices dreht sich nicht nur um Technologie — es ist eine Veränderung der Art und Weise, wie das Team arbeitet. Conway’s Law gilt: Die Architektur eines Systems spiegelt die Struktur der Organisation wider. Wenn Sie unabhängige Dienste wollen, brauchen Sie unabhängige Teams.
Für uns war es der richtige Schritt. Aber wir würden ihn nur unter der Bedingung wiederholen, dass wir ein ausreichend großes Team und klare Domänengrenzen haben.
Brauchen Sie Hilfe bei der Implementierung?
Unsere Experten helfen Ihnen bei Design, Implementierung und Betrieb. Von der Architektur bis zur Produktion.
Kontaktieren Sie uns