Zum Inhalt springen

Monolith aufteilen

Monolith zu Microservices: der erste Service in 20 Tagen

Elf Jahre Commits in einem Deployable, vierhundert Tabellen in einem Schema, ein Release-Zug, der einmal im Quartal abfährt. Wir finden, wo die Daten wirklich auseinandergehen, trennen zuerst das Schema und schneiden einen Service heraus, der für sich baut, deployt und alarmiert. Rails, Django, Spring, .NET, PHP oder Go: Die Methode ist dieselbe, und der zweite Service geht schneller, weil der harte Teil hinter Ihnen liegt.

Angebot anfordernFünf Felder. Ein Entwickler meldet sich damit, wo die Nähte vermutlich liegen.

20 Tage für den ersten Service, schneller beim zweiten


Zwei Services und eine Bibliothek. Die Zahl der Services sollte zur Zahl der Teams passen, die dafür Bereitschaft tragen können.

Ein Deployable

Ein Repository, ein Schema, ein Release-Zug, Importe, die im Kreis laufen.

  • one deployable11 years of commits
  • shared schema400+ tables
  • release trainquarterly
  • circular importscycles

Geteilt

Zwei Services mit eigenen Schemata, eine Bibliothek für das Gemeinsame, getrennte Deploys.

  • billingGo · own schema
  • catalogueGo · own schema
  • shared kernellibrary
  • deploysper service

20 Tage für den ersten Service, schneller beim zweiten

Zwei Services und eine Bibliothek. Die Zahl der Services sollte zur Zahl der Teams passen, die dafür Bereitschaft tragen können.

Wie die Arbeit läuft

Die Datenbank wird getrennt, bevor Code umzieht. Diese Reihenfolge ist der Unterschied zwischen einem umkehrbaren Projekt und einem schlechten Jahr.
  1. 01Tag 1–4

    Die Nähte in den Daten finden

    Query-Logs zeigen, welche Tabellen im selben Request zusammen gelesen werden. Dort liegen die Grenzen, was auch immer die Paketstruktur behauptet.

  2. 02Tag 3–8

    Zuerst das Schema trennen

    Tabellen aufteilen und die Joins über die Grenze entfernen, solange alles noch ein Deployable ist. Das meiste Risiko liegt in diesem Schritt, und in diesem Stadium ist er noch umkehrbar.

  3. 03Tag 8–15

    Einen Service herausziehen

    Den mit den wenigsten eingehenden Abhängigkeiten, und das ist selten der, der am meisten nervt. Er läuft hinter derselben Schnittstelle, bis der Betrieb langweilig wird.

  4. 04Tag 14–20

    Ihm eine eigene Pipeline geben

    Eigenes Repository, eigener Deploy, eigene Bereitschaft. Wenn Releases weiterhin mit dem Monolithen abgestimmt werden müssen, war nichts gewonnen, und das zeigt sich an Tag fünfzehn und nicht am Ende.

Was die Plattform macht, was ein Mensch macht

Kandidaten für Nähte zu finden ist Messen, und die Plattform macht das aus Ihren eigenen Query-Logs. Zwischen ihnen zu wählen hängt daran, wem was gehört, und dafür sitzt ein Entwickler mit Ihren Leads zusammen.
Eine Naht stimmt, wenn nach der Extraktion die meisten Änderungen nur eine Seite berühren.
Was die Plattform macht, was ein Mensch machtWer macht wasAnmerkungen
Gemeinsame Tabellenzugriffe und Modulkopplung kartierenPlattformAus Query-Logs und dem Aufrufgraphen, über einen Zeitraum, der den Monatsabschluss einschließt.
Die Nähte vorschlagenGemeinsamDie Plattform sortiert die Kandidaten. Ein Mensch prüft sie gegen Ihre Teamgrenzen.
Die Joins über die Grenze auflösenPlattformMechanische Arbeit, als Pull Requests geprüft, in kleinen Stücken ausgeliefert.
Wählen, welcher Service zuerst gehtEntwicklerWem was gehört, entscheidet das öfter als der Code.
TransaktionsgrenzenEntwicklerWo eine Datenbanktransaktion früher über die Naht ging, muss jemand entscheiden, was im Fehlerfall passiert.
CI, Deploy und BereitschaftGemeinsamEin Service ohne eigene Pipeline und eigene Bereitschaft ist ein Modul mit zusätzlichen Netzwerksprüngen.

Wer die Naht schneidet

Dutzende Migrationen, über zehn Jahre an Systemen, die von längst gegangenen Leuten gebaut wurden, und genug Aufteilungen, um zu wissen, welche sich auszahlen. Monolithen in Rails, Django, Spring, .NET, PHP und Go, Schemata mit vierhundert Tabellen und zehn Jahren Joins über die Grenze. Die Naht liegt nie dort, wo das Architekturdiagramm sie zeichnet, und die echte zu finden ist das meiste, was Sie einkaufen.


Die erste Extraktion ist die Prüfung, und sie ist abgegrenzt: ein Service, eigenes Schema, eigener Deploy, im Produktivbetrieb. Sie bekommen eine belastbare Antwort zum Preis einer Phase.

Fragen, die Entwickler uns stellen

Mit wie vielen Services sollten wir enden?
Mit weniger als im Diagramm der Architekturpräsentation. Ziehen Sie einen heraus, betreiben Sie ihn ein Quartal im Produktivbetrieb und entscheiden Sie dann über den nächsten. Teams, die vorab zwölf planen, bekommen meist vier und viel gemeinsame Datenbank.
Müssen wir in Go neu schreiben?
Nein. Extraktion und Neuschreiben sind getrennte Entscheidungen, und viele Aufteilungen bleiben in der ursprünglichen Sprache. Wo wir einen Service doch neu schreiben, lag es daran, dass dieses Modul ohnehin neu geschrieben worden wäre, egal wo es gewohnt hätte.
Was passiert mit gemeinsam genutztem Code?
Er wird eine versionierte Bibliothek mit kleiner Oberfläche. Wenn der gemeinsame Kern in jedem Sprint wächst, ist das das Signal, dass die Naht an der falschen Stelle lag, und sie früh im Projekt zu verschieben kostet einen Bruchteil dessen, was sie im zweiten Jahr kostet.
Geht das, während wir Features liefern?
Ja, und es wird dadurch langsamer. Zu schützen ist der Schritt der Schematrennung: Feature-Arbeit dort dazwischenzuschieben ist der Weg, auf dem diese Projekte ein Jahr lang mit halb geteilter Datenbank stehenbleiben.
Was ist mit der gemeinsamen Datenbank, vor der alle warnen?
Deshalb kommt das Schema zuerst. Zwei Services auf einem Schema sind ein verteilter Monolith mit schlechteren Fehlerbildern als der Ausgangszustand, und das ist die häufigste Art, diese Arbeit schlecht zu machen.

Fangen Sie mit einer Extraktion an

Größe, Release-Frequenz und das, was die Änderung erzwingt, reichen für eine erste Antwort. Wir kommen damit zurück, wo die Nähte zu liegen scheinen und was der erste Service kosten würde.

Angebot anfordern

Ein Entwickler antwortet, und die erste Frage gilt normalerweise Ihrer Release-Frequenz.