Świat IT co pewien czas nawiedzają fale popularności. Nie można nie zauważyć jak nowa technologia czy idea rozlewa się zachłannie po slajdach głównych prezentacji na konferencjach, czy też pojawia się intensywnie na branżowych blogach, manifestując bycie na TOP’ie. Po pamiętnych czasach WebServices, ORM, TDD, DDD czy potem NoSql, dzisiaj nie sposób nie zauważyć, że jednym z obecnych informatycznych krzyków mody są „Microservices”.
Idea ta oficjalnie funkcjonuje jako wzorzec architektury dla systemów serwerowych klasy enterprise i w założeniach jest bardzo prosta. Dzielimy system na (dające się wydzielić) fragmenty, separujemy je, w znacznym stopniu zapewniając im własną „piaskownicę” zarówno w zakresie kontenerów danych, zasobów, transakcji, jak i np. zespołów developerskich czy cykli wydawniczych. Do każdego fragmentu specyfikujemy wyraźny interface dostępowy z jasnym kontraktem i komunikacją opartą o jawne i wieloplatformowe protokoły (np. HTTP). Do tego dodajemy kontener, który sprawnie takimi mikro usługami instrumentuje i skoordynuje ich działanie. W efekcie otrzymujemy aplikację, system, który tak naprawdę jest konglomeratem wielu współpracujących ze sobą dynamicznie modułów (serwisów).
Jakie są korzyści? Zwolennicy powyższego mówią, że:
- każdy mikroserwis jest stosunkowo mały, co daje:
– jest łatwy do zrozumienia przez developera,
– stanowi małe obciążenie dla IDE,
– pozwala na szybki start kontenera,
– szybciej startują i wykonują się testy, - każdy mikroserwis można dostarczać niezależnie od innych serwisów, z różnym cyklem wydawniczym włącznie,
- każdy mikroserwis można wytwarzać w innym zespole w innej lokalizacji nawet przy użyciu innych narzędzi, technologii i języków,
- każdy mikroserwis działa jako odrębna aplikacja, proces, czy instancja maszyny wirtualnej, wiec jego „problemy” nie wpływają na działanie innych serwisów,
- każdy mikroserwis może być wytwarzany w różnych technologiach, więc łatwiej jest wprowadzać nowe technologie do projektu,
- każdy mikroserwis będzie lepiej zaprojektowany, skoro jest mniejszy i ma dobrze zdefiniowany interface to daje to dużą szansę na lepszą architekturę.
Nie można w pierwszym odruchu odmówić słuszności tych stwierdzeń, choć bez podania kontekstu, w którym mają one być (i są na pewno) słuszne, chwilami „włos się jeży”. Dodajmy także głosy sceptyczne wytykające wady:
- komplikuje się proces wytwarzania systemu, system staje się zbiorem małych systemów, które trzeba zgrać, zsynchronizować,
- testowanie, choć jednostkowo prostsze w układzie testowania całego złożonego systemu jest wyraźnie trudniejsze ze znaczną rozbudową testów integracyjnych,
- transakcje to potencjalny koszmar tej architektury, jeżeli pozostają w obrębie poszczególnych mikroserwisów, to problem nie istnieje, jeżeli transakcje rozpinają się ponad mikroserwisami … zostaje „distributed transaction”, znacznikowanie, programowe rollback’i czy inne zabawy „dużych chłopaków”,
- przy podziale zakładającym, że każdy mikroserwis ma własny kontener na dane, możliwe także że oparty o inne fizyczne i techniczne medium, pobieranie danych przekrojowych może zakończyć się koniecznością implementacji wzorca Visitor, tworzeniem JOIN’ów na poziomie aplikacyjnym czy np. wykorzystaniem architektury CQRS z wyspecjalizowanymi, zdublowanymi źródłami danych poddanymi denormalizacji,
- trudniej zapanować nad jakością i spójną architekturą poszczególnych serwisów, które są wytwarzane przy użyciu różnych technik i poprzez różne zespoły,
- zarządzanie, monitorowanie i utrzymanie środowiska złożonego z wielu odrębnych aplikacji może stanowić nie małe wyzwanie, i jakkolwiek dobre narzędzia pozwalają to robić wydajnie, to jednak pozostaje to coś, co robić trzeba,
- zwiększone zapotrzebowanie na zasoby, w przypadku kiedy zamiast jednej dużej aplikacji mamy wiele mniejszych czasami nawet posiadających swoją własną maszynę wirtualną bezdyskusyjnie rośnie nam zapotrzebowanie na pamięć operacyjną.
Nie odważę się na ocenę, która strona ma racje, wybrnę dyplomatycznie, że obie. Zalety i wady mikroserwisów są oczywiste i trudno z nimi dyskutować, jednak warto jak zawsze zdefiniować kontekst. Jaki mamy projekt, jakie wymagania, które z wad aplikują się do naszego przypadku, które z korzyści na nas spłyną, czy w naszym przypadku to się opłaci.
Niezaprzeczalne jest jednak to, że sama idea podziału czegoś dużego, z czym (ze względu na skale) mamy problem, na mniejsze elementy, z którymi z osobna problemu nie mamy, przy zachowaniu akceptowalnych kosztów synchronizacji tych elementów, jest słuszna i obiema rekami się pod nią podpisuję.
Krzysztof Olszewski
Dyrektor Technologii i Architektury Oprogramowania
Krzysztof Olszewski
Dyrektor Technologii i Architektury Oprogramowania