Introduktion
“Skal vi bruge mikroservices?” er et af de mest almindelige arkitekturspørgsmål, jeg bliver stillet. Svaret er næsten altid “det kommer an på”, men det er ikke særlig hjælpsomt. Denne artikel giver en konkret ramme til at træffe denne beslutning.
Den ærlige sandhed
De fleste teams, der indfører mikroservices for tidligt, fortryder det. Kompleksitetsoverheadet er betydeligt, og fordelene viser sig først ved bestemte skalaer.
Jeg har set:
- Et 5-mands startup med 20 mikroservices, der kæmper med at levere funktioner
- En virksomhed med 200 ansatte og en velstruktureret monolit, der bevæger sig hurtigere end konkurrenterne
Arkitekturen bør matche din kontekst, ikke dine ambitioner.
Hvornår monolitter vinder
Små til mellemstore teams (< 50 udviklere)
Med et mindre team:
- Kommunikationsoverheadet er lavt
- Delt kodeejerskab fungerer
- Koordinering af deployments er overkommelig
- Man har ikke råd til det driftsmæssige overhead ved distribuerede systemer
Produkter i en tidlig fase
Når man stadig finder ud af:
- Hvilke funktioner brugerne ønsker
- Hvor domænegrænserne ligger
- Hvad ydelseskravene er
En monolit giver mulighed for hurtigere iteration og nem refaktorering.
Simple domæner
Hvis din forretningslogik er ligetil og ikke har naturlige grænser, skaber det at tvinge mikroservices igennem kunstig kompleksitet.
Hvornår mikroservices vinder
Store teams (50+ udviklere)
I stor skala:
- Teams har brug for autonomi for at bevæge sig hurtigt
- Koordinering af deployments bliver en flaskehals
- Forskellige dele af systemet har forskellige skaleringsbehov
Klare domænegrænser
Når du har:
- Adskilte forretningsfunktioner (betalinger, lagerbeholdning, forsendelse)
- Forskellige krav til dataejerskab
- Teams tilpasset forretningsdomæner
Forskellige tekniske krav
Når dele af dit system har brug for:
- Forskellige sprog eller frameworks
- Forskellige skaleringsegenskaber
- Forskellige deploymentfrekvenser
- Forskellige pålidelighedskrav
Beslutningsrammen
Vurdér din situation ud fra disse faktorer:
Teamstørrelse og -struktur
| Situation | Score |
|---|---|
| < 10 udviklere, ét team | Monolit (+3) |
| 10-30 udviklere, 2-4 teams | Begge dele (0) |
| 30-50 udviklere, flere teams | Slanke mikroservices (+1) |
| 50+ udviklere, mange teams | Mikroservices (+3) |
Domænekompleksitet
| Situation | Score |
|---|---|
| Simpelt, samlet domæne | Monolit (+2) |
| Nogle adskilte underdomæner | Begge dele (0) |
| Klare bounded contexts | Mikroservices (+2) |
Deploymentbehov
| Situation | Score |
|---|---|
| Ugentlige releases er fint | Monolit (+2) |
| Daglige releases nødvendige | Begge dele (0) |
| Flere daglige, uafhængige releases | Mikroservices (+2) |
Skaleringskrav
| Situation | Score |
|---|---|
| Ensartet belastning på tværs af funktioner | Monolit (+1) |
| Nogle funktioner kræver mere skalering | Begge dele (0) |
| Vidt forskellige skaleringsbehov | Mikroservices (+2) |
Fortolkning:
- Score > 3: Stærk kandidat til monolit
- Score -2 til 3: Begge dele fungerer, overvej teamets præference
- Score < -2: Stærk kandidat til mikroservices
Den modulære monolit: Det bedste fra begge verdener
Før du springer til mikroservices, bør du overveje en modulær monolit:
src/
├── modules/
│ ├── users/
│ │ ├── api/
│ │ ├── domain/
│ │ └── infrastructure/
│ ├── orders/
│ │ ├── api/
│ │ ├── domain/
│ │ └── infrastructure/
│ └── payments/
│ ├── api/
│ ├── domain/
│ └── infrastructure/
└── shared/
└── kernel/
Fordele:
- Klare grænser uden netværksoverhead
- Nem at udtrække til services senere
- Én deployment, enklere drift
- Håndhævede modulgrænser gennem kodestrukturen
Migreringsvej
Hvis du starter med en monolit og har brug for at migrere:
1. Identificér kandidater til udtrækning
Kig efter moduler, der:
- Har klare grænser
- Har brug for uafhængig skalering
- Har forskellige deploymentbehov
- Ejes af et bestemt team
2. Strangler fig-mønstret
Skriv ikke om - udtræk gradvist:
- Sæt en facade foran monolitten
- Udtræk én funktion til en service
- Dirigér trafik til den nye service
- Gentag
3. Start ved kanterne
Udtræk services, der:
- Har færre afhængigheder
- Er mindre kritiske (lavere risiko)
- Har klare grænseflader
Almindelige fejl
For tidlig opdeling
At opdele, før man forstår domænet, fører til forkerte grænser. Det er meget sværere at sammenlægge services end at opdele en monolit.
Distribueret monolit
Hvis dine services:
- Skal deployes sammen
- Deler en database
- Har synkrone afhængigheder overalt
Så har du en distribueret monolit - hele kompleksiteten, ingen af fordelene.
At ignorere driftsomkostninger
Mikroservices kræver:
- Service discovery
- Distribueret tracing
- Log-aggregering
- Containerorkestrering
- Mere kompleksitet i vagtordningen
Sørg for, at du har råd til dette overhead.
Et eksempel fra den virkelige verden
En virksomhed, jeg rådgav, havde 30 udviklere og 15 mikroservices. De kæmpede med:
- Langsom udvikling af funktioner (ændringer berørte flere services)
- Hyppige integrationsproblemer
- Kompleks deploymentkoordinering
- Højt driftsmæssigt overhead
Vi konsoliderede til 4 services tilpasset teamgrænserne:
- Kerneplatform (delt)
- Kundevendt produkt
- Interne værktøjer
- Datapipeline
Resultat:
- 40 % hurtigere levering af funktioner
- 60 % færre produktionshændelser
- Gladere udviklere
Konklusion
Debatten om mikroservices vs. monolit handler ikke om, hvad der er “bedst” - den handler om, hvad der passer til din kontekst.
Start med en velstruktureret monolit. Tilføj klare modulgrænser. Udtræk kun til services, når du har en konkret grund: teamautonomi, uafhængig skalering eller forskellige tekniske krav.
Den bedste arkitektur er den, der lader dit team levere værdi til brugerne hurtigt og pålideligt. Nogle gange er det mikroservices. Ofte er det ikke.