Mikroserwisy, czy też mikrousługi, to jeden z największych buzzword’ów ostatnich lat. Okazuje się jednak, że jest z nim trochę jak z seksem nastolatków – wszyscy mówią, że to robią, ale w rzeczywistości doświadczenie mają tylko nieliczni. Co trzeba zrobić, żeby dobrze wykorzystać ten rodzaj architektury? Jakie warunki musimy spełnić, aby wniósł on coś więcej w naszą pracę niż tylko zapis w CV? O tym przeczytacie w tym wpisie.

Ale to już było…

Kilka lat temu na konferencjach królowała architektura SOA (Service Oriented Architecture). W dużym skrócie, polega ona na budowie dużych systemów z wielu zintegrowanych ze sobą, podzielonych logicznie usług. W założeniu miało to wyeliminować główne problemy związane z architekturą monolityczną. Większość wdrożeń SOA opierała się bądź też migrowała z czasem w kierunku wykorzystania szyny integracyjnej (Enterprise Service Bus). Szyna odpowiadała za routing komunikacji, mapowanie dokumentów, obsługę różnych rodzajów endpoint’ów, audytowanie i bezpieczeństwo. Idea była szczytna, jednak wszechstronność rozwiązania okazała się bronią obosieczną. Po pewnym czasie szyna przeradzała się w kolejny monolit. Centralizacja, wąskie gardło zarówno rozwojowe, jak i wydajnościowe, czy pojedynczy punkt awarii (single point of failure) przyczyniały się do rosnącej krytyki rozwiązania. Znam przypadki, w których nad szyną pracował 60–80-osobowy zespół, a nawet to nie wystarczało i część komunikacji trzeba było puszczać bezpośrednio, aby tylko nie blokować projektów biznesowych.

Architektura mikroserwisów, będąca de facto implementacją stylu SOA, opiera się właśnie na wnioskach wyciągniętych podczas korzystania z modelu ESB. Zasadniczej zmianie uległ sposób komunikacji. Trzon rozwiązania to już nie wszechwładna szyna, ale wymiana informacji punkt-punkt (point-to-point). Z założenia ma to wyeliminować wąskie gardło i pozwolić na niezależny rozwój projektów.

Mikroserwisy nie są mikro

Jak małe są mikroserwisy? Jedną z bardziej wątpliwych metod oceny rozmiaru aplikacji jest liczba linii kodu. Na początek będzie ona jednak wystarczająca. Najczęstsza odpowiedź na pytanie, „ile linii kodu powinien mieć statystyczny mikroserwis”,  to „1000”. Nie chciałbym stawiać się w roli wyroczni, oceniając, czy to dobrze, czy źle. Sięgnijmy jednak po wsparcie matematyki (z pierwszych klas szkoły podstawowej). Przyjmijmy, że średnia wielkość jednej aplikacji monolitycznej (rozwijanej przez 20–30-osobowy zespół) to pół miliona linii kodu. Jeżeli podzielmy to na komponenty po tysiąc linii, w teorii otrzymamy 500 serwisów. To niewiele mniej niż mają giganci typu Netflix czy Uber. Na całą firmę. Rozwijanych przez blisko dwa tysiące inżynierów. A my mamy 30. Czy to znaczy, że trzeba zatrudnić dodatkowo 1970 osób, żeby przejść na nową architekturę? Czy może jednak lepiej zmienić poziom granulacji?

Przyjmując, że nad jednym serwisem może pracować 3–5 osób, nasz monolit podzielmy przykładowo na 8 aplikacji. Każda z nich będzie miała średnio ok. 60 tysięcy linii. I to jest już bardziej realne. Jako programista bez problemu mogę ogarnąć szczegółowo aplikację tej wielkości. Można w niej także zaimplementować konkretny kawałek biznesu i skutecznie rozwijać go niewielkim, zwinnym zespołem.

W głowie może rodzić się natomiast pytanie – co właściwie jest nie tak z małymi serwisami? Czemu mam ufać innym? Po pierwsze, warto zauważyć, że ich rozwiązania działają bardzo dobrze, co może być wyznacznikiem właściwego toku rozumowania. To właśnie dostępność platformy jest głównym powodem takiej, a nie innej granulacji aplikacji. W przypadku wykorzystania synchronicznej komunikacji między usługami, ujawnia się zjawisko określane jako „temporal coupling”. Do kontynuacji procesowania transakcji biznesowej konieczne jest uzyskanie odpowiedzi od drugiej usługi. Ta druga może z kolei wołać trzecią i tak dalej. Im większa jest taka „synchroniczna głębokość systemu”, tym mniejsza jego dostępność.

Nie mam użytkowników – czy mikroserwisy mi pomogą?

Wokół mikroserwisów narosło bardzo dużo mitów. Jeżeli miałbym wierzyć we wszystko, co o nich słyszałem na konferencjach, prawdopodobnie upierałbym się, że dług publiczny i głód na świecie można rozwiązać, rozbijając monolity na mikrousługi. Nie muszę nawet komentować, jaka to bzdura. (A może jednak muszę? Nie wierzcie ślepo we wszystko co Wam mówią na konferencjach!)

Czym mikroserwisy różnią się od klasycznego systemu rozproszonego? Słuchając kuluarowych dyskusji, można dojść do wniosku, że jest to informatyczny odpowiednik przechwalania się ceną czy wielkością samochodu. „Ile masz mikroserwisów? Bo my mamy 400”. Szczerze mówiąc, ja wolę mieć 40 porządnych, niż 400 nastrzelanych tylko po to, żeby mieć się czym pochwalić przed znajomymi. Ale co ja tam wiem. Podstawowa różnica między mikroserwisami a klasycznym systemem rozproszonym leży w autonomii. System rozproszony, mimo że realizuje proces za pomocą wielu rozdzielnych systemów, koncepcyjnie przypomina monolit. Wszystkie systemy są aktualizowane wspólnym wdrożeniem i często nawet nie obsługują niedostępności kolaboratorów (aplikacji, z którymi się komunikują). W mikroserwisach jest zupełnie inaczej. Każdy serwis ma swój cykl życia. Prace nad poszczególnymi aplikacjami prowadzone są niezależnie i wdrażane bez koordynacji. Nie jest niczym niezwykłym sytuacja, w której usługa, od której jesteśmy zależni, nie jest dostępna, bo akurat trwa wdrożenie nowej wersji.

Autonomia ta jest ogromną siłą mikroserwisów. Pozwala na prawdziwie zwinny i skalowalny rozwój systemu. Odchodzą do lamusa dyskusje typu: „nie można teraz wdrażać projektu X, bo projekt Y jeszcze nie wytestował swoich poprawek”. Niestety, ta niezależność powoduje także, że mikroserwisy są zdecydowanie najtrudniejszą architekturą, z jaką pracowałem. Konieczność stałej pracy w modelu „design for failure” i przewidywania zawczasu wszelkich problemów związanych z komunikacją, przyprawiają o ból głowy nawet najlepszych programistów i architektów. Z drugiej strony, jeżeli biznes nie jest gotowy pracować w takim modelu i naciska na pozostanie w modelu release’owym, mikroserwisy tracą jedną ze swoich największych wartości. A koszty i problemy pozostają.

Gdzie są granice?

Jednym z najtrudniejszych zadań przy wdrażaniu architektury mikrousług jest prawidłowe określenie ich granic. Pierwszym przybliżeniem jest tutaj znany z Domain Driven Design koncept Bounded Context’u. W każdym kontekście istnieje zazwyczaj ekspert domenowy, będący często biznesowym właścicielem realizowanych tam procesów. Co za tym idzie, ograniczenie wielkości aplikacji do obszaru zarządzanego biznesowo przez jedną osobę, gwarantuje większy ład i spójność niż w przypadku konieczności godzenia różnych grup interesów. Kolejnymi istotnymi aspektami do rozważenia są także własność danych i kroki procesów biznesowych. Jeżeli dwa pozornie rozłączne konteksty wpływają na te same dane, może to oznaczać, że podział na nie jest sztuczny. Może też jednak okazać się, że niezbędne jest wyznaczenie trzeciego niezależnego kontekstu, zarządzającego danymi wykorzystywanymi w innych procesach.

Powyżej wymieniłem główne, aczkolwiek nie jedyne kryteria podziału serwisów. Jeżeli jedna z funkcji może być zdecydowanie efektywniej zrealizowana w innej technologii (np. zaimplementowana w innym języku) niż główny serwis, warto rozważyć ich rozdzielenie. Podobnie wygląda kwestia skalowalności. Wiedząc, że określone funkcje będą wykorzystywane bardzo intensywnie, warto rozważyć wyniesienie ich do osobnego komponentu. Trzecim, często rozpatrywanym aspektem jest bezpieczeństwo. Jeżeli wymagania w tym zakresie znacząco różnią się między poszczególnymi funkcjami, wrzucanie ich do jednej aplikacji może nie być najlepszym pomysłem.

TLDR

Jakie są podstawowe kryteria stosowalności mikroserwisów? Warto rozważyć wejście w tę architekturę, jeżeli:

  1. Biznes, z którym pracujesz, jest gotowy porzucić klasyczny release’owy model pracy.
  2. Poszczególne jednostki biznesowe potrafią autonomicznie realizować projekty.
  3. Potrzebujesz dynamicznej i asymetrycznej skalowalności.

Zapraszam gorąco do dyskusji w komentarzach.

15
Dodaj komentarz

avatar
7 Comment threads
8 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
9 Comment authors
Jakub KubryńskiDSINCZAKAdam RoszykPiotrKamil Recent comment authors
  Subscribe  
najnowszy najstarszy oceniany
Powiadom o
Kaizen
Gość
Kaizen

Jakbym to pokazał w pracy to by mnie w*******

Karol
Gość
Karol

Podoba mi się Twoja analiza. Czy ten jednodniowy warsztat będzie dostępny online/via streming?

Sebastian
Gość
Sebastian

A co jeżeli usługi komunikują się przez np. RabbitMQ? Z jednej strony pozwala nam to na zmniejszenie couplingu pomiędzy usługami i zwiększenie autonomiczności poszczególnych usług, natomiast wprowadza nam to singiel point of failure. Co byś polecił do monitoringu RabbitMQ? Z góry wielkie dzięki za info.

Kamil
Gość
Kamil

Rozumiem, że jeżeli wierzy Pan, że problemu długu publicznego nie można rozwiązać, to również wierzy Pan, że można go w nieskończoność pogłębiać? Akurat słabe zestawienie w porównaniu do głodu na świecie, którego faktycznie nie da się wyeliminować. Polecam unikać swoich osobistych przemyśleń na zjawiska nie związane z tematem.

Pozdrawiam.

Piotr
Gość

Cześć 🙂

Bardzo ciekawe podsumowanie, chętnie bym zgłębił ten temat na warsztatach, jednak link nie działa – da radę to poprawić?

Pozdrawiam!
Piotrek

Adam Roszyk
Gość
Adam Roszyk

Po dzisiejszych warsztatach w TomTomie w Poznaniu mam deja vu. To jest dokładnie to co chcieliśmy przekazać dzisiaj na naszym wystąpieniu. Cieszę się, że zmienia się podejście do konferencji i że zaczynamy dostrzegać wartość w wymianie wiedzy między programistami, a nie w reklamowaniu produktów i technologii. Będę musiał wybrać się na Devoxxa w takim razie, bo wróciła mi wiara w konferecje:-) pozdrowienia z Poznania!

DSINCZAK
Gość
DSINCZAK

Od samego początku myślałem trendzie mikroserwisów jako o SOA. Gdyby trochę się zagłębić to pierwotnie podejście SOA miało więcej z mikroserwisów niż z tego, czym się rzeczywiście stało. Szyny ESB pogrążyły SOA, ale głównym powodem było złe zrozumienie tej architektury i złe wyznaczanie granic usług. Przykładem może być sprzedaż produktu gdzie w źle zrobionym SOA usługa sprzedaży pytała np. usługę magazynu o produkty. W rzeczywistości ta usługa powinna mieć wszystkie informacje o produktach u siebie i synchronizować je z modułem magazynu. Innymi słowy, każda usługa powinna mieć wszystkie informacje u siebie któe są jej potrzebne do wykonania zadań. Jednak skończyło… Czytaj więcej »