Mr Monolit vs. Mikrotjänster. The battle of the century
Låt mig presentera slagskämparna! I den röda ringhörnan står en tidigare titelmästare i tungvikt - Mr Monolit. I den blå hörnan finns ett ungt och uppumpat gäng av mikrotjänster från fjäderviktsklassen.
Låt mig presentera slagskämparna! I den röda ringhörnan står en tidigare titelmästare i tungvikt - Mr Monolit. I den blå hörnan finns ett ungt och uppumpat gäng av mikrotjänster från fjäderviktsklassen.
Jag har sett flera allvarliga monoliter i mitt liv. En av dem hade ungefär 5+ timmars byggtid och företaget var tvunget att bygga sin egen CI för att fortsätta framåt.
Å andra sidan såg jag människor som använde mikrotjänster. De behövde 17 lastbalanserare för att få igång sin “pre-Alpha” lösning. Det roliga är att de var före sin tid med att köra “infrastructure-as-code”.
Om du frågade mig för ungefär fem år sedan skulle jag säga att monoliten är ond och mikrotjänster är bra. Den praktiska erfarenheten under dessa år har dock lärt mig att det lätt kan ge bakslag om man väljer mikrotjänster-vägen.
Låt mig hoppa över att prata om monolitproblemen (det är inte meningsfullt att slå på den döda hästen). Låt mig koncentrera mig lite på problemen med mikrotjänster.
Det finns många saker utöver kodning som måste göras för att ha en färdig produkt (göra en build, köra tester, driftsättning, övervakning, skalning osv.) Allt detta behöver man räkna ut bara en gång för en monolit. Det måste dock upprepas för var och en av mikrotjänsterna. I bästa fall är dina mikrotjänster baserade på en liknande teknikstack för att kunna återanvändas. I värsta fall måste du uppfinna hjulet på nytt för var och en av dem. (En liten anmärkning: En del av dessa smärtor löses gradvis med hjälp av verktyg, men bara en del av dem).
Vem ska vakna klockan två på natten om din tjänst börjar halta? Ett dedikerat Ops-team för monoliten har vanligtvis tillräckligt med kunskap för att lösa problemen (och låta dig hantera resten på 8:00 på morgonen). Så snart du har hundratals mikrotjänster hamnar du ganska ofta med ett par personer (eller kanske till och med bara en) som vet hur man håller den specifika tjänsten vid liv. Det är inte roligt att väckas klockan två på natten bara för att någon övervakning hade ett falskt positivt resultat. Dessutom ökar detta otroligt mycket de operativa riskerna (vad händer när den enda personen som känner till en viss mikrotjänst är på semester någonstans där det inte finns något internet)?
Att flytta kod inom en monolit och ändra gränssnitt är i allmänhet inte så illa. Att flytta kod mellan mikrotjänster och ändra gränssnitt (inklusive hantering av versionshantering och bakåtkompatibilitet) är krävande.
Historiken med gränssnittsändringar blir särskilt smärtsam om du inte delade upp din applikation perfekt första gången och upptäcker att vissa delar av logiken hör till fel mikrotjänst. Och jag kan lova att du inte har delat upp den perfekt. Det skulle vara naivt att anta att det man gjorde för ett år sedan kommer vara korrekt efter ett år.
Monolith använder samma språk, ramverk och så vidare. Därför är det lätt att flytta människor mellan olika delar av en monolit. Det är svårt att flytta människor mellan olika mikrotjänster (som kan ha olika kompetenser).
Det är minst sagt smärtsamt att felsöka något i en uppsättning mikrotjänster. Alla som har varit tvungna att jaga ett fel mellan 4-5 mikrotjänster fram och tillbaka i flera dagar för att upptäcka att en av dem inte utförde någon validering kan förstå det.
Jag är ganska säker på att det finns många andra nackdelar. Men även denna lista får mig att ifrågasätta mikrotjänster som lösning.
Vad ska vi göra?
Det största problemet är inte monolit i sig (eller mikrotjänster i sig), utan snarare extremer som leder till. Och tyvärr kan det hända att team/företag inte känner igen problemen i tid och börjar åtgärda dem förrän de har spårat ur helt och hållet.
Monoliten blir stor och tenderar att fortsätta växa och försämras. När man inser att det är ett problem är det redan så stort och hårigt att det blir en nästan omöjlig uppgift att bryta ner det.
Mikrotjänster växer i antal och komplexiteten i deras interaktioner., Och som ett resultat ger det alla de problem som jag beskrivit ovan.
Min åsikt är att man måste ha rätt storlek på tjänsterna :) Först och främst tror jag att det är en bra idé att börja med en någorlunda monolitisk arkitektur (en eller ett par tjänster). När de började växa, leta efter naturliga sprickor (kodstycken med mycket olika attribut). Det är dessa bitar som successivt kan separeras till fristående tjänster.
För att ge dig ett exempel. Jag arbetade med en backend-tjänst där vi upptäckte att en del kallades mycket oftare än andra. Den behöver skalas horisontellt och snabbare än resten. Vi upptäckte också att den nuvarande arkitekturen för den här delen var lite problematisk, och den hade en liten mängd beroenden på resten av backend-tjänsten. Jaha, här har du en perfekt kandidat för att extraheras som en separat tjänst!