Prečo nestačí „robiť microservices“: architektúra, ktorá prežije realitu
Moderná architektúra sa nespozná podľa toho, koľko má mikroslužieb, eventov a cloud-native nálepiek. Spozná sa podľa toho, ako sa správa vtedy, keď sa veci pokazia. A práve tam sa ukáže rozdiel medzi systémom, ktorý dobre vyzerá na diagrame, a systémom, ktorý vie obstáť v produkčnej realite.
V IT si občas radi zamieňame prostriedok za cieľ. Keď sa povie „moderný systém“, veľmi rýchlo začneme hovoriť o mikroslužbách, event-driven architektúre,
Kubernetes, service meshoch, observabilite či resiliencii. To všetko sú relevantné témy. Ale samy o sebe ešte negarantujú, že staviame dobrý systém.
Dobrá architektúra totiž nevzniká tým, že poskladáme správne technológie. Vzniká tým, že robíme správne rozhodnutia v správnom kontexte.
A to je podstatne ťažšie.
Architektúra nie je diagram
Za roky v architektúre som si potvrdil jednu jednoduchú vec: navrhnúť systém, ktorý funguje, je len prvý krok. Skutočná výzva je navrhnúť systém, ktorý bude fungovať aj o dva roky, pri vyššej záťaži, s ďalšími integráciami, viacerými tímami a úplne iným tlakom zo strany biznisu.
Na začiatku býva všetko čisté. Zodpovednosti dávajú zmysel, integračné rozhrania sú zrozumiteľné, doménové hranice sú ešte čitateľné a tímy vedia, kto za čo zodpovedá.
Problém neprichádza na začiatku.
Prichádza neskôr. Keď sa do jednej služby pridá logika „len dočasne“. Keď pribudne ďalšie synchronné volanie, ktoré „veď nič nepokazí“. Keď sa obíde navrhnutý proces, lebo treba niečo dodať rýchlo. Keď sa niekde skopírujú dáta, ale už sa presne neurčí, kto je ich vlastník.
Architektúra sa nekazí naraz. Kazí sa postupne.
A práve preto je dobré na ňu nepozerať ako na jednorazový návrh, ale ako na sériu dôležitých rozhodnutí, ktoré sa budú testovať realitou každý ďalší mesiac.
Najväčší problém nebýva technológia, ale zodpovednosť
Keď sa hovorí o škálovaní systémov, diskusia sa veľmi rýchlo stočí k infraštruktúre. Koľko inštancií, aký autoscaling, aký messaging broker, aký throughput, aká databáza.
To všetko je dôležité. Ale iba vtedy, ak máme jasno v tom, kto je za čo zodpovedný.
Ak systém nemá jasné hranice, škálovanie v praxi často znamená len to, že chaos začneme šíriť rýchlejšie a do väčšieho priestoru.
Dobre navrhnutá architektúra nemusí byť jednoduchá, ale musí byť čitateľná. Musí byť zrejmé:
- kde sa validuje vstup,
- kde sa rozhoduje o biznis pravidlách,
- kde sa riešia integrácie,
- kde vzniká zdroj pravdy,
- a kto nesie zodpovednosť za výsledok procesu.
Ak tieto hranice rozmažeme, vznikne systém, kde každý komponent robí trochu zo všetkého. Výsledkom býva architektúra, ktorá sa tvári moderne a distribuovane, ale v skutočnosti len rozkladá monolitické myslenie do viacerých deployovateľných jednotiek.
To však nie je distribuovaná architektúra.
To je distribuovaný problém.
Synchronné volania sú pohodlné. A práve preto nebezpečné
Synchronný svet je príjemný. Request príde, spracuje sa, klient dostane odpoveď. Flow je intuitívny, implementácia priamočiara, debugging relatívne komfortný.
Lenže každé ďalšie synchronné volanie zvyšuje krehkosť celého procesu.
Pridáva latenciu. Zvyšuje riziko timeoutu. Vytvára nový bod zlyhania. A čo je najhoršie, po chybe často zanecháva neistotu.
To je podľa mňa jeden z najväčších praktických problémov distribuovaných systémov. Nie samotný timeout, ale neistota po ňom.
- Spracovala sa operácia celá?
- Len čiastočne?
- Je bezpečné ju zopakovať?
- Nevytvoríme duplicitu?
- Vie klient korektne pokračovať?
Práve tu sa ukáže, či bola architektúra navrhovaná ako technické cvičenie, alebo ako seriózna príprava na reálnu prevádzku.
Idempotencia nie je detail. Je to disciplína
Ak by som mal vybrať jednu vlastnosť, ktorá je v distribuovaných systémoch podceňovaná viac, než by si zaslúžila, bola by to idempotencia.
Nie ako pekný pojem v dokumentácii. Ale ako vedomé architektonické rozhodnutie, že systém musí vedieť bezpečne spracovať opakovaný pokus bez nežiaducich vedľajších efektov.
Prečo je to také dôležité?
Pretože klient veľmi často nevie, či operácia po timeout-e prebehla alebo nie. A úplne prirodzene ju skúsi znova. Ak backend s týmto scenárom ráta, všetko je v poriadku. Ak nie, veľmi rýchlo sa dostaneme k duplicitám, nekonzistentným stavom a incidentom, ktoré sa ťažko hľadajú a ešte ťažšie vysvetľujú.
Retry mechanizmy, timeouty či circuit breakery majú svoje miesto. Ale bez idempotencie bývajú často len čiastočnou odpoveďou.
Systém, ktorý nevie bezpečne zvládnuť opakovaný pokus, nie je odolný. Je len optimistický.
Event-driven architektúra nie je automaticky odpoveď
Keď sa tím popáli na príliš veľkej synchronnosti, prirodzene príde protiargument: poďme to robiť asynchrónne. Eventy predsa znižujú previazanosti, zlepšujú škálovanie a zvyšujú odolnosť.
Áno. Ale nie zadarmo.
Asynchrónna architektúra nevyrieši problémy magicky. Len ich vymení za inú triedu problémov.
Získame voľnejšie väzby medzi komponentmi, ale zároveň si berieme eventual consistency, komplikovanejší tracing, náročnejší debugging a vyššie nároky na
prevádzkovú disciplínu. Kým pri synchronnom flow vieme často presne, kde proces zlyhal, pri eventoch vieme niekedy iba to, že „sa to niekde po ceste stratilo“.
Preto event-driven prístup nevnímam ako cieľ, ku ktorému sa má každý systém automaticky dopracovať. Vnímam ho ako veľmi silný nástroj, ktorý funguje výborne tam, kde presne vieme, prečo ho používame.
Ak ním však iba maskujeme zle navrhnuté synchronné toky, problém sme nevyriešili. Len sme ho presunuli inam.
Technicky správne ešte neznamená prevádzkovo vhodné
V architektúre existuje jedna častá pasca: navrhnúť riešenie, ktoré je koncepčne elegantné, ale prevádzkovo nepraktické.
Na papieri všetko sedí. Hranice sú čisté, patterny použité správne, komponenty oddelené. Lenže reálny tím s tým v praxi bojuje, delivery sa spomaľuje a systém sa začne postupne deformovať.
Nie preto, že by ľudia zlyhali.
Ale preto, že návrh nerešpektoval ich realitu.
Architektúra nikdy neexistuje vo vákuu. Je prepojená s ľuďmi, tímami, spôsobom delivery, úrovňou ownershipu aj s tým, ako organizácia zvláda prevádzku. Dobrý architekt preto nenavrhuje len „správny systém“. Navrhuje systém, ktorý je správny pre konkrétny kontext. A to je zásadný rozdiel.
Observabilita sa nepridáva na konci
V distribuovaných systémoch býva observabilita často vnímaná ako niečo, čo sa doladí neskôr. Keď bude čas, pridáme logy. Potom metriky. Potom tracing. Potom alerty.
To je drahá chyba.
Ak od začiatku nevieme, ako budeme systém pozorovať v produkcii, v skutočnosti ho len dúfame. A medzi „pozorovať“ a „dúfať“ je v prevádzke veľmi nepríjemný rozdiel.
Každý dôležitý proces by mal byť navrhnutý tak, aby sme vedeli odpovedať na základné otázky:
- Kde sa proces začal?
- Aké rozhodnutie sa cestou urobilo?
- Ktorý komponent zlyhal?
- V akom stave zostali dáta?
- Vie klient bezpečne pokračovať?
- Vieme incident spätne zrekonštruovať?
Ak na tieto otázky nevieme odpovedať, máme funkcionalitu. Nie spoľahlivý systém.
Najlepšia architektúra býva často najmenej nápadná
Čím dlhšie sa pohybujem v architektúre, tým viac si cením riešenia, ktoré nemajú potrebu byť za každú cenu efektné.
Nepotrebujú každú novú technológiu. Nepotrebujú extrémnu distribúciu tam, kde nie je potrebná. Nepotrebujú komplikovať veci len preto, aby pôsobili moderne.
Najlepšie systémy, s ktorými som sa stretol, bývali často tie, ktoré umožňovali tímom robiť správne rozhodnutia prirodzene. Mali jasné hranice, zrozumiteľné integračné vzory, predvídateľné správanie pri chybe a dostatočnú viditeľnosť nad tým, čo sa v nich deje.
Neboli dokonalé.
Ale boli stabilné, pochopiteľné a evolvovateľné.
A to je v praxi oveľa cennejšie než architektonická dokonalosť v prvej verzii diagramu.
Architektúra sa overuje až v realite
Na záver možno jedna jednoduchá myšlienka: architektúra nie je úspešná v momente, keď ju schválime. Ani v momente, keď ju nasadíme. Je úspešná až vtedy, keď prežije realitu.
Produkčnú záťaž. Chyby. Timeouty. Rast systému. Zmeny priorít. Tlak biznisu. Nové integrácie. Ďalšie tímy.
Ak po týchto skúškach stále vieme povedať, že systém je čitateľný, riaditeľný a dôveryhodný, potom sme pravdepodobne navrhli niečo správne.
A možno práve to je dnes najväčšia výzva architektúry: nemať potrebu postaviť to najmodernejšie riešenie, ale postaviť také, ktoré obstojí aj vtedy, keď moderné slová z prezentácie už dávno nikoho nezaujímajú.
Pretože dobrá architektúra sa nespozná podľa toho, ako vyzerá v ideálnom stave.
Spozná sa podľa toho, ako sa správa v ten najhorší deň.
