Microservices
Womit alles anfängt: der Monolith
Ein Monolith ist eine Anwendung, die als ein Stück gebaut, ausgeliefert und gestartet wird. Eine .jar-Datei, eine Datenbank, ein Prozess.
Genau so sieht dein Gästebuch aus. Und dein Webshop. Und die allermeisten Anwendungen, die je geschrieben wurden.
Der Begriff klingt nach Altlast, beschreibt aber nur eine Bauform — und meistens die richtige. Ein Monolith ist einfach zu bauen, einfach zu testen, einfach zu betreiben. Eine Datenbanktransaktion umspannt das ganze System. Ein Methodenaufruf kann nicht im Netzwerk verlorengehen.
Wer mit Microservices anfängt, weil sie moderner klingen, zahlt einen hohen Preis für ein Problem, das er noch gar nicht hat.
Wo der Monolith eng wird
Solange er klein ist, gar nicht. Die Probleme kommen mit der Größe und mit der Anzahl der Menschen, die daran arbeiten.
| Was passiert | Warum es beim Monolithen weh tut |
|---|---|
| Ein Team wartet auf das andere | Alle liefern gemeinsam aus. Wer fertig ist, wartet auf den, der es nicht ist |
| Eine Änderung, alles neu testen | Ein Fehler im Rechnungsdruck kann den Warenkorb betreffen — man weiß es nicht sicher |
| Ein Absturz, alles weg | Ein Speicherleck im Bildimport reißt die ganze Anwendung mit |
| Eine Technologie für alles | Die Bildverarbeitung wäre in einer anderen Sprache besser aufgehoben — geht aber nicht |
| Skalieren nur im Ganzen | Nur die Suche ist überlastet? Trotzdem wird alles vervielfacht |
Der letzte Punkt ist der greifbarste.
Der Schnitt: waagerecht oder senkrecht?
Bevor es um Microservices geht, lohnt eine Zwischenstufe — und sie erklärt, warum manche Monolithen altern und andere nicht.
Ein Monolith ist meist in Schichten geteilt: Web-Schicht, Fachlichkeit, Datenzugriff. Das ist ein waagerechter Schnitt, und du kennst ihn aus Tutorial 04. Innerhalb einer Anwendung ist das genau richtig.
Der andere Schnitt geht senkrecht: nicht nach technischer Aufgabe, sondern nach Fachlichkeit. Alles, was zu „Bestellung" gehört — Oberfläche, Regeln, Tabellen —, liegt beieinander.
Diese senkrechten Streifen tragen einen Namen: Self-Contained Systems, im deutschsprachigen Raum oft schlicht Vertikalen. Jede Vertikale ist für sich lauffähig, hat ihre eigenen Daten und ihre eigene Oberfläche.
Der Unterschied zwischen einem alternden Monolithen und einem, mit dem man in zehn Jahren noch arbeiten kann, ist nicht die Anzahl der Prozesse. Es ist der Schnitt.
Ein senkrecht geschnittener Monolith lässt sich später in Dienste zerlegen, weil die Grenzen schon da sind. Ein waagerecht geschnittener nicht — dort verläuft jede fachliche Grenze quer durch alle Schichten.
Erst richtig schneiden, dann verteilen. Wer verteilt, ohne geschnitten zu haben, bekommt einen Monolithen mit Netzwerk dazwischen — alle Nachteile beider Bauformen.
Was Microservices sind
Ein Microservice ist eine Vertikale, die als eigener Prozess läuft und über das Netzwerk angesprochen wird.
Die Merkmale, die zusammengehören:
| Merkmal | Was es bedeutet |
|---|---|
| Fachlich geschnitten | Ein Dienst gehört zu einem Fachgebiet, nicht zu einer technischen Schicht |
| Unabhängig auslieferbar | Der Katalog-Dienst geht live, ohne dass Versand angefasst wird |
| Eigene Datenhaltung | Kein anderer Dienst greift auf seine Tabellen zu — nur über seine Schnittstelle |
| Über das Netz erreichbar | Meist per HTTP und JSON — also mit genau dem, was du in diesem Lernfeld baust |
| Ein Team pro Dienst | Ein Dienst ist klein genug, dass ein Team ihn ganz versteht |
Es klingt nach einer Nebensache, ist aber die Regel, an der die meisten Umbauten scheitern: Zwei Dienste greifen nie auf dieselben Tabellen zu.
Sobald der Versand-Dienst direkt in die Katalog-Tabellen schreibt, sind beide wieder aneinandergekettet — die Datenbank ist dann die gemeinsame Kupplung, und keiner der beiden lässt sich noch allein ändern. Man hat die Nachteile des Monolithen behalten und die Nachteile des Netzwerks dazugekauft.
Der Preis dieser Regel: Daten liegen mehrfach vor, und sie sind nicht in derselben Sekunde überall gleich.
Was es kostet
Ein Methodenaufruf im Monolithen kann nicht fehlschlagen. Ein Netzwerkaufruf kann immer fehlschlagen. Das ist der Kern aller Nachteile.
| Was im Monolithen selbstverständlich ist | Was daraus bei Microservices wird |
|---|---|
| Methodenaufruf, Nanosekunden | Netzwerkaufruf, Millisekunden — und er kann ausbleiben |
| Eine Transaktion über alles | Jeder Dienst hat seine eigene; über Dienstgrenzen gibt es keine gemeinsame |
| Ein Log, eine Fehlermeldung | Eine Anfrage hinterlässt Spuren in fünf Logs |
| Beim Kompilieren fällt auf, wenn ein Aufruf nicht mehr passt | Fällt erst zur Laufzeit auf — die Schnittstelle ist ein Versprechen, kein Vertrag, den der Compiler prüft |
| Eine Anwendung starten | Zehn Dienste starten, in der richtigen Reihenfolge |
Deshalb der oft zitierte Rat: Fang mit einem Monolithen an. Zerlege ihn, wenn du weißt, wo die Grenzen wirklich verlaufen — und nicht vorher, denn vorher weiß es niemand.
„Microservices sind moderner, also besser."
Sie sind eine Antwort auf ein Organisationsproblem: viele Menschen, die gleichzeitig an einem System arbeiten und sich nicht gegenseitig blockieren sollen. Wer dieses Problem nicht hat, hat auch den Nutzen nicht — zahlt aber den vollen Preis.
Es gibt gute Gründe für Microservices und gute Gründe dagegen. Was es nicht gibt, ist ein Grund, sie zu nehmen, weil sie neuer klingen.
Was ein Anwendungsentwickler darüber wissen muss
Du wirst als Auszubildende oder Auszubildender keine Systemarchitektur entwerfen. Du wirst aber sehr wahrscheinlich an einem Dienst arbeiten, der einer von vielen ist. Dafür ändert sich einiges an der täglichen Arbeit:
1. Deine Schnittstelle ist ein Versprechen.
Andere Teams verlassen sich darauf. Ein Feld umbenennen ist kein Refactoring mehr, sondern ein Bruch. Deshalb: neue Felder hinzufügen ja, vorhandene entfernen oder umdeuten nein — jedenfalls nicht ohne neue Version. Das ist auch der Grund, warum die Adresse /api/**v1**/… heißt.
2. Fremde Dienste fallen aus. Immer.
Nicht „falls", sondern „wann". Was dein Code deshalb braucht: einen Timeout bei jedem Aufruf (sonst wartest du ewig), eine Entscheidung, was ohne die fremde Antwort passieren soll, und einen Statuscode, der ehrlich ist — 503, wenn du gerade nicht liefern kannst.
3. Derselbe Aufruf kommt manchmal zweimal.
Wenn eine Antwort ausbleibt, versucht der Aufrufer es erneut — obwohl deine Arbeit vielleicht schon getan war. Ein POST, der zweimal ankommt, darf nicht zwei Bestellungen anlegen. Das nennt man Idempotenz, und im Infoblatt Das REST-Paradigma steht, welche HTTP-Methoden sie von sich aus mitbringen und welche nicht.
4. Dein Dienst merkt sich nichts zwischen zwei Anfragen. Wenn drei Kopien deines Dienstes laufen, landet die zweite Anfrage vielleicht bei einer anderen als die erste. Alles, was zwischen zwei Anfragen erhalten bleiben soll, gehört in die Datenbank — nicht in ein Feld der Klasse.
5. Einstellungen kommen von außen. Datenbankadresse, Zugangsdaten, die Adresse des Nachbardienstes — nichts davon steht im Quelltext. Es kommt aus Umgebungsvariablen, damit dasselbe Image in Entwicklung, Test und Betrieb laufen kann.
6. Schreib Logs, an denen man eine Anfrage verfolgen kann. Wenn eine Bestellung durch vier Dienste läuft, will jemand später wissen, wo sie steckengeblieben ist. Dafür bekommt jede Anfrage eine Kennung, die mitgereicht und in jede Logzeile geschrieben wird.
Die Verbindung zu diesem Lernfeld
Alles, was du in den Tutorials baust, ist genau das Handwerkszeug, aus dem Microservices bestehen:
| Was du gelernt hast | Wozu es im Verbund dient |
|---|---|
| REST-Endpunkte mit sauberen Adressen | So sprechen Dienste miteinander |
| Statuscodes mit Bedeutung | So erfährt der Aufrufer, ob es geklappt hat — ohne den Rumpf zu lesen |
| DTOs statt Entitäten | So bleibt die Schnittstelle stabil, wenn sich die Datenbank ändert |
| OpenAPI | So weiß das andere Team, was dein Dienst kann |
| Automatisierte Tests | So merkst du, dass du dein Versprechen brichst, bevor der andere es merkt |
| Docker | So wird dein Dienst vervielfacht, ohne dass jemand etwas installiert |
Ein einzelner Spring-Boot-Dienst mit eingebautem Webserver, in einen Container gepackt: Das ist die übliche Bauform eines Microservice. Du baust sie bereits — nur eben bisher allein und nicht im Verbund.
Filme
Alle auf Deutsch:
| Film | Wofür |
|---|---|
| Was ist ein Microservice? (predic8) | Der Einstieg: Nachteile des Monolithen, Aufteilung in Dienste |
| Monolithen vs. Microservices (the native web) | Der direkte Vergleich beider Bauformen |
| Warum ein Monolith oft besser ist als Microservices (predic8) | Die Gegenrede — sieh dir diesen als zweiten an |
Nach zwei begeisterten Filmen bleibt leicht hängen: „Monolith alt, Microservices neu." Der dritte räumt das wieder ab — und erst mit beiden Seiten kann man die Frage beurteilen, statt sie zu glauben.
Das Wichtigste in Kürze
- Ein Monolith ist eine Anwendung aus einem Stück. Das ist meistens die richtige Wahl.
- Er wird eng, wenn viele Menschen gleichzeitig daran arbeiten und wenn nur ein Teil unter Last steht.
- Entscheidend ist der Schnitt: waagerecht nach Technik, senkrecht nach Fachlichkeit. Senkrechte Streifen heißen Vertikalen oder Self-Contained Systems.
- Ein Microservice ist eine Vertikale als eigener Prozess, mit eigener Datenhaltung, unabhängig auslieferbar, über das Netz erreichbar.
- Der Preis: Netzwerk statt Methodenaufruf, keine gemeinsame Transaktion, viele Logs, mehr Betrieb.
- Für dich heißt das: stabile Schnittstelle, Timeouts, Idempotenz, kein Zustand im Dienst, Einstellungen von außen.
Weiterlesen
- Docker und Container — die Verpackung, in der Dienste ausgeliefert werden
- Das REST-Paradigma — Idempotenz, sichere Methoden, Ressourcenschnitt
- Was ist ein Webservice? — die Grundlage darunter