Mikroservisy: Proč nahradily monolity

Mikroservisy: Proč nahradily monolity

Od monolitů k mikroservisům

Mikroservisy jsou architektonický styl, ve kterém je aplikace složena z malých, samostatně nasaditelných služeb komunikujících přes síť pomocí jasně definovaných rozhraní. Každá služba implementuje úzce vymezené obchodní schopnosti a je nezávislá z hlediska vývoje, nasazení, škálování i volby technologií. Tento přístup kontrastuje s monolitem, v němž jsou logika systému, data i uživatelská rozhraní zabaleny do jednoho spustitelného artefaktu, který se nasazuje jako celek.

Proč monolity dlouho dominovaly a kde narážejí

  • Jednodušší začátek: jediný repozitář, jednotné testy, „jeden build – jedno nasazení“.
  • Silná konzistence v rámci jednoho procesu (transakce, sdílené objekty, společné knihovny).
  • Limity růstu: těžkopádná vydávání, pomalé buildy, vysoká míra vzájemných závislostí, obtížné škálování pouze části systému.
  • Organizační překážky: do stejné codebase zasahuje mnoho týmů; fronty na vydávání, střety priorit, integrace „velkým třeskem“.

Definice mikroservisů a klíčové vlastnosti

  • Samostatné nasazování: každá služba se nezávisle verzije, sestavuje a vydává.
  • Obchodně orientované rozhraní: API popisuje doménové schopnosti, nikoli tabulky či interní objekty.
  • Vlastnictví dat: každá služba má své úložiště (polyglotní persistence); mezi službami se nesdílí databázové schéma.
  • Izolace poruch: chyba v jedné službě nevyřadí celý systém.
  • Nezávislé škálování: služby se škálují podle vlastního zatížení, nikoli podle největšího společného jmenovatele.

Proč mikroservisy nahradily monolity (v mnoha případech)

  • Rychlost změn: menší codebase pro každý tým, kratší doba od změny k nasazení, možnost nasazovat několikrát denně.
  • Organizační sladění: Conwayův zákon – týmy tvoří služby, které odrážejí jejich komunikační struktury; odpovědnost od nápadu až po provoz (vyvíjíš, provozuješ).
  • Technologická volnost: každá služba může pro daný problém zvolit nejvhodnější nástroj (jazyk, framework, databázi).
  • Odolnost a škálování: horizontální škálování pouze tam, kde je třeba; postupné omezení funkcí při částečných výpadcích.

Doménový návrh a hranice služeb

Základem kvalitního rozdělení je Domain-Driven Design (DDD). Systém dělíme podle ohraničených kontextů – relativně autonomních oblastí podnikání se samostatným modelem a jazykem.

  • Heuristiky rozdělení: vysoká soudržnost uvnitř, nízká provázanost navenek; stabilní API na hranici; odlišné tempo změn.
  • Antivzor: dělení podle vrstev (UI/Service/DB) vede k minimonolitům a těsnému provázání.
  • Kontrakty: explicitní API (REST/JSON, gRPC, GraphQL), schémata a verze (SemVer), testování kontraktů řízené potřebami konzumentů.

Komunikace: synchronní vs. asynchronní

  • Synchronní (HTTP/gRPC): jednoduchá integrace, přímé dotazy; riziko kaskádových timeoutů – nutné jsou přerušovač okruhu, časové limity, opakované pokusy s prodlužovaným odstupem a oddělení zdrojů.
  • Asynchronní (události, zprostředkovatel zpráv): volné vazby, lepší odolnost a škálovatelnost; vyžaduje idempotenci, deduplikaci a outbox; exactly-once nelze bez kompromisů očekávat.
  • Architektura řízená událostmi: služby publikují doménové události (OrderPlaced), na které ostatní reagují; snižuje potřebu orchestrátorů.

Konzistence dat: od ACID k eventual consistency

V distribuovaném systému nelze spoléhat na transakce napříč službami. Místo toho:

  • Ságy: choreografie (reakce na události) nebo orchestrace (centrální koordinátor) s kompenzačními kroky.
  • Vzor Outbox: atomický zápis změny a události do lokální databáze a následné spolehlivé publikování.
  • Čtecí modely: materializované pohledy pro rychlé čtení, CQRS pro oddělení zápisu a čtení.

API Gateway, BFF a okrajová vrstva

  • API Gateway: jednotný vstupní bod, autentizace/autorizace, omezení počtu požadavků, směrování, observabilita, transformace.
  • Backend for Frontend (BFF): specializované API pro jednotlivé klienty (web/mobil) – snižuje množství drobných požadavků a složitost v uživatelském rozhraní.
  • GraphQL / agregace: vhodné pro složité dotazy napříč službami (pozor na problém N+1 a latenci).

Observabilita a provoz

  • Logy: strukturované (JSON), korelační ID/ID trasování propagovaná napříč všemi službami.
  • Metriky: klíčové signály (latence, chybovost, provoz, saturace), obchodní metriky (např. úspěšnost objednávek).
  • Trasování: distribuované trasování (W3C Trace Context, OpenTelemetry) – vizualizuje závislosti a latenci.

Odolnost a řízení selhání

  • Přerušovač okruhu a oddělení zdrojů izolují chyby; časové limity a opakované pokusy s exponenciálně se prodlužujícím odstupem a náhodným rozptylem.
  • Omezování počtu požadavků, zařazování do front, omezování zátěže a paralelní záložní požadavky pomáhají řídit špičky.
  • Chaos engineering a dny provozních cvičení ověřují připravenost na výpadky.

Bezpečnost: zero-trust a řízení identity

  • mTLS mezi službami, obměna certifikátů, identita služby (SPIFFE/SPIRE) a krátkodobé tokeny.
  • Princip nejnižších oprávnění v API i databázích, ABAC/RBAC, politiky jako kód (OPA).
  • Dodavatelský řetězec: podepsané obrazy, SBOM, skenování zranitelností, izolace tajných údajů (KMS/Secrets).

Nasazení, škálování a běhové prostředí

  • Kontejnery a orchestrátor (Kubernetes): deklarativní nasazení, automatické škálování (HPA/VPA), postupné a kanárkové vydávání, kontroly readiness/liveness pro ověření stavu.
  • Service mesh (Istio/Linkerd): jednotná observabilita, TLS, pravidla provozu bez změn aplikačního kódu.
  • CI/CD: pipeline s testy, bezpečnostními kontrolami, příznaky funkcí a rychlou strategií návratu k předchozí verzi.

Testování v mikroservisním světě

  • Kontraktní testy: brání skrytým změnám API, které narušují zpětnou kompatibilitu.
  • Integrační testy a testy od začátku do konce: selektivní scénáře kritických toků; náročné komplexní testy od začátku do konce nahrazujte syntetickými testy a stínovým provozem.
  • Správa testovacích dat: deterministická data, naplnění výchozími daty, izolace prostředí.

Data a persistence: vlastnictví a polyglotní přístup

  • Každá služba vlastní své schéma a publikuje změny prostřednictvím API/událostí, nikoli přímým přístupem k cizí databázi.
  • Polyglotní persistence: typ úložiště vybírejte podle domény (relační databáze, dokumenty, časové řady, graf).
  • Migrace: migrace jako kód, strategie rozšíření a následného zúžení, nasazení blue-green pro rizikové změny.

Verzování a kompatibilita

  • Zpětná kompatibilita jako výchozí požadavek; tolerantní čtenář na straně klienta.
  • Registr schémat a validace (OpenAPI/JSON Schema/Protobuf); řízené ukončování podpory s metrikami využití.

Organizační model a správa

  • Platformový tým zajišťuje CI/CD, observabilitu, šablony a základní bezpečnostní standardy.
  • Produktové týmy nesou komplexní odpovědnost za služby (kód, infrastruktura, SLO); rozhraní odpovědností jsou jasně vymezená.
  • Lehká správa: katalog služeb, standardy telemetrie, bezpečnostní zásady, ale také svoboda volby v rámci stanovených pravidel.

Strategie migrace z monolitu

  • Strangler Fig: kolem monolitu vzniká nová fasáda, jednotlivé schopnosti se postupně vyčleňují do samostatných služeb.
  • Oddělení dat: vrstva ochrany před cizím modelem, replikace/streamování změn (CDC), postupné vypínání tabulek.
  • Stanovení priorit podle přínosu: začněte v doménách s častými změnami, problémy se škálováním či potřebou inovací.

Antivzory a časté chyby

  • Distribuovaný monolit: mnoho služeb, ale těsné vazby, koordinovaná vydávání, sdílená databáze – ztráta výhod a nárůst složitosti.
  • Předčasné rozdělení na příliš malé části: příliš jemné členění zvyšuje režii, latenci a nároky na koordinaci.
  • Chybějící observabilita a řízení chyb → obtížná diagnostika a dlouhá doba do obnovení služby (MTTR).
  • Nejasné doménové hranice: „prosakující“ modely a křehká API.

Náklady a kompromisy

  • Provozní složitost: více artefaktů, více běžících instancí, vyšší nároky na SRE a platformu.
  • Daň za latenci: síťová komunikace, serializace, více přenosových kroků – nutná je optimalizace toků a ukládání do mezipaměti.
  • Bezpečnostní plocha: více hranic, více tajných údajů – vyžaduje přísnější standardy a automatizaci.

Osvědčené postupy pro úspěšné mikroservisy

  • Začněte s DDD a mapou ohraničených kontextů; vyhněte se technickému dělení.
  • Upřednostňujte integrace řízené událostmi, idempotenci a outbox pro zajištění spolehlivosti.
  • Standardizujte telemetrii (logy/metriky/trasování) a základní bezpečnostní standardy (mTLS, tajné údaje, zásady).
  • Automatizujte CI/CD a platformu (šablony, osvědčené postupy); zkraťte dobu od změny k nasazení bez obětování kvality.
  • Definujte SLO/SLI a používejte rozpočty chyb k řízení rychlosti změn.

Závěr: kdy (ne)zvolit mikroservisy

Mikroservisy přinášejí rychlejší inovace, nezávislé škálování a odolnost, ale za cenu vyšší distribuované složitosti. Jsou vhodné pro doménově rozmanité systémy s více týmy, potřebou rychlých cyklů vydávání a pružného škálování. U malých produktů nebo raných MVP může být efektivnější modulární monolit s čistě vymezenými hranicemi a případný přechod na mikroservisy až později, v závislosti na růstu. Správně uplatněná mikroservisní architektura – opřená o DDD, události, přísné provozní standardy a kulturu vyvíjíš, provozuješ – pak představuje robustní základ pro dlouhodobě udržitelné a škálovatelné systémy.