Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

19 września w Moskwie miał miejsce pierwsze tematyczne spotkanie HUG (Highload++ User Group), które było poświęcone mikroserwisom. Zanotowaliśmy wykład „Eksploatacja mikroserwisów: rozmiar ma znaczenie, nawet jeśli masz Kubernetes”, w którym podzieliliśmy się bogatym doświadczeniem firmy „Flant” w zakresie eksploatacji projektów z architekturą mikroserwisową. Przede wszystkim będzie on przydatny dla wszystkich programistów zastanawiających się nad zastosowaniem tego podejścia w swoim obecnym lub przyszłym projekcie.

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Prezentujemy wideo z wykładem (50 minut, znacznie bardziej informacyjne niż artykuł), a także główną treść w formie tekstowej.

NB: Wideo i prezentacja są również dostępne na końcu tej publikacji.

Wprowadzenie

Zazwyczaj dobra historia ma wprowadzenie, główny wątek i zakończenie. Ten wykład bardziej przypomina wprowadzenie, co więcej, tragiczne. Ważne jest również, aby zauważyć, że prezentuje on perspektywę mikroserwisów z punktu widzenia eksploatację.

Zacznę od takiego wykresu, którego autorem (w 2015 roku) zaczął Martin Fowler:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Na nim widać, jak w przypadku monolitycznej aplikacji, która osiągnęła określony rozmiar, zaczyna spadać produktywność pracy. Mikroserwisy różnią się tym, że początkowa produktywność z nimi jest niższa, jednak w miarę wzrostu złożoności degradacja efektywności nie jest tak zauważalna.

Uzupełnię ten wykres dla przypadku użycia Kubernetes:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Dlaczego aplikacja z mikroserwisami się poprawiła? Ponieważ taka architektura stawia poważne wymagania, które są świetnie spełniane przez możliwości Kubernetes. Z drugiej strony, część tej funkcjonalności będzie przydatna również dla monolitu, szczególnie z tego powodu, że typowy dzisiaj monolit to nie do końca monolit (szczegóły zostaną omówione później w wykładzie).

Jak widać, ostateczny wykres (gdy zarówno aplikacje monolityczne, jak i mikroserwisowe znajdują się w infrastrukturze Kubernetes) niewiele różni się od początkowego. Następnie będziemy mówić o aplikacjach eksploatowanych z użyciem Kubernetes.

Pożyteczność i szkodliwość mikroserwisów

I tu główna myśl:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Czym jest normalna architektura mikroserwisowa? Powinna przynosić ci rzeczywiste korzyści, zwiększając efektywność pracy. Jeśli wrócimy do wykresu, oto ona:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Jeśli nazwiemy ją przydatna, to po drugiej stronie wykresu znajdzie się szkodliwa mikroserwisowość (przeszkadza w pracy):

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Wracając do "głównej myśli": czy w ogóle warto zaufać mojemu doświadczeniu? Od początku tego roku obejrzałem 85 projektów. Nie wszystkie z nich były mikroserwisowe (taka architektura miała około jednej trzeciej do połowy z nich), ale to wciąż duża liczba. Nam (firmie „Flant”) jako dostawcom zewnętrznym udaje się dostrzegać różnorodność aplikacji, rozwijanych zarówno w małych firmach (z 5 programistami), jak i w dużych (~500 programistów). Dodatkowym plusem jest to, że widzimy, jak te aplikacje żyją i rozwijają się przez wiele lat.

Po co mikroserwisy?

Na pytanie o użyteczność mikroserwisów jest bardzo konkretny odpowiedź od wspomnianego już Martina Fowlersa:

  1. wyraźne granice modularności;
  2. niezależne wdrażanie;
  3. wolność wyboru technologii.

Dużo rozmawiałem z architektami i programistami oprogramowania i pytałem, dlaczego potrzebują mikroserwisów. Sporządziłem swoją listę ich oczekiwań. Oto, co wyszło:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Jeśli opisać "w odczuciu" niektóre z punktów, to:

  • wyraźne granice modułów: oto mamy straszny monolit, a teraz wszystko będzie starannie uporządkowane w repozytoriach Git, w których wszystko jest "na półkach", nie pomieszane ciepłe z miękkim;
  • niezależność wdrażania: będziemy mogli wdrażać usługi niezależnie, aby rozwój przebiegał szybciej (równolegle publikować nowe funkcje);
  • niezależność w rozwijaniu: możemy oddać ten mikroserwis temu zespołowi/programiście, a tamten — innemu, dzięki czemu będziemy mogli szybciej rozwijać;
  • bwiększąwiększa niezawodność: jeśli wystąpi częściowa degradacja (jedna z 20 mikroserwisów upadnie), to przestanie działać tylko jeden przycisk, a cały system nadal będzie funkcjonować.

Typowa (szkodliwa) architektura mikroserwisów

Aby wyjaśnić, dlaczego w rzeczywistości wszystko nie jest takie, jak oczekujemy, przedstawię zbiorowy obraz architektury mikroserwisowej, oparty na doświadczeniach z wielu różnych projektów.

Przykładem będzie abstrakcyjny sklep internetowy, który planuje konkurować z Amazonem lub przynajmniej OZON. Jego architektura mikroserwisowa wygląda następująco:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Z wielu powodów te mikroserwisy są napisane na różnych platformach:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Ponieważ każdy mikroserwis powinien być autonomiczny, wiele z nich potrzebuje własnej bazy danych i cache'a. Ostateczna architektura przedstawia się następująco:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Jakie są jej konsekwencje?

Fowler ma w tej kwestii artykuł – o 'zapłacie' za korzystanie z mikrousług:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Zobaczymy, czy nasze oczekiwania się spełniły.

Wyraźne granice modułów...

Ale ile mikrousług musimy naprawdę poprawić, aby wprowadzić zmianę? Czy w ogóle możemy zrozumieć, jak to wszystko działa, bez rozproszonego narzędzia do śledzenia (przecież każde zapytanie jest obsługiwane przez połowę mikrousług)?

Istnieje wzorzec 'dużej kulki brudu', a tutaj mamy całkowicie rozproszoną kulkę brudu. Oto przykładowa ilustracja tego, jak przebiegają zapytania:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Niezależność wdrożenia...

Pod względem technicznym została osiągnięta: możemy zaktualizować każdą mikrousługę oddzielnie. Ale w praktyce trzeba pamiętać, że zawsze wdrażanych jest wiele mikrousług, musimy również uwzględnić kolejność ich wdrożenia. Powinniśmy w ogóle testować w oddzielnym otoczeniu, czy wdrażamy wersję w odpowiedniej kolejności.

Wolność wyboru technologii...

Jest. Tylko trzeba pamiętać, że często wolność graniczy z chaosem. Ważne jest, aby nie wybierać technologii tylko po to, aby 'pobawić się' nimi.

Niezależność w rozwoju...

Jak stworzyć testowe otoczenie dla całej aplikacji (z tak wielu komponentów)? A przecież trzeba to również utrzymywać w aktualnym stanie. To wszystko prowadzi do tego, że rzeczywista liczba testowych otoczeń, które możemy utrzymać, okazuje się minimalna.

A jak wdrożyć to wszystko lokalnie? Okazuje się, że często programista wykonuje swoją pracę niezależnie, ale "na ślepo", ponieważ jest zmuszony czekać, aż otoczenie do testowania się zwolni.

Oddzielne skalowanie...

Tak, ale jest to ograniczone w zakresie używanych baz danych. W podanym przykładzie architektura nie sprawia problemów z Cassandra, ale będą one z MySQL i PostgreSQL.

Bwiększąardzo większa niezawodność...

Nie tylko to, że w rzeczywistości awaria jednej mikrousługi często łamie poprawne działanie całego systemu, to pojawia się jeszcze nowy problem: uczynić każdą mikrousługę odporną na awarie jest bardzo trudne. Ponieważ w mikrousługach używane są różne technologie (memcache, Redis itd.), dla każdej z nich trzeba wszystko przemyśleć i wdrożyć, co, oczywiście, jest możliwe, ale wymaga ogromnych zasobów.

Mierzenie obciążenia…

Z tym naprawdę wszystko w porządku.

„Lekkość” mikroserwisów…

Mieliśmy nie tylko ogromne narzuty sieciowe (wzrastające zapytania do DNS itd.), ale także z powodu licznych zapytań zaczęliśmy replikować dane (przechowywać pamięci podręczne), co doprowadziło do znacznej ilości przechowywania.

I oto jak wygląda zgodność z naszymi oczekiwaniami:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Ale to jeszcze nie wszystko!

Ponieważ:

  • Prawdopodobnie będziemy potrzebować szyny komunikacyjnej.
  • Jak zrobić spójny backup w odpowiednim czasie? Jedyną realną opcją jest wyłączenie ruchu na ten czas. Ale jak to zrobić na produkcji?
  • Jeśli mówimy o wsparciu wielu regionów, zorganizowanie odporności w każdym z nich to bardzo pracochłonne zadanie.
  • Pojawia się problem wprowadzania zmian w sposób centralny. Na przykład, jeśli musimy zaktualizować wersję PHP, będziemy musieli dokonać commitu w każdym repozytorium (a jest ich dziesiątki).
  • Wzrost operacyjnej złożoności zdaje się być wykładniczy.

Co z tym wszystkim zrobić?

Zacznijcie od monolitycznej aplikacji. Doświadczenie Fowlera mówi dotyczy tego, że prawie wszystkie udane aplikacje mikroserwisowe zaczynały się od monolitu, który stał się zbyt duży, a następnie został podzielony. Równocześnie prawie wszystkie systemy zbudowane jako mikroserwisowe od samego początku, prędzej czy później napotykały poważne problemy.

Jeszcze jedna cenna myśl — aby projekt z architekturą mikroserwisową odniósł sukces, musisz bardzo dobrze znać zarówno dziedzinę przedmiotu, jak i to, jak robić mikroserwisy. A najlepszym sposobem na poznanie dziedziny przedmiotu jest stworzenie monolitu.

Ale co zrobić, jeśli już znaleźliśmy się w takiej sytuacji?

Pierwszym krokiem do rozwiązania jakiegokolwiek problemu jest zaakceptowanie go i zrozumienie, że to problem, że nie chcemy już cierpieć.

Jeśli w przypadku rozrośniętego monolitu (kiedy brak jest możliwości dokupienia zasobów) przecinamy go, to w tym przypadku mamy odwrotną sytuację: gdy nadmierna mikroserwisowość już nie pomaga, a przeszkadza — przecinajcie to, co zbędne i łączcie!

Na przykład, dla rozważanego powyżej zbiorczego obrazu…

Pozbądźcie się najbardziej wątpliwych mikroserwisów:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Połączcie wszystkie mikroserwisy odpowiedzialne za generację frontendu:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

… w jednej mikroserwisie, napisanym w jednym (nowoczesnym i dobrym, jak uważacie) języku/frameworku:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Będzie miał jedną ORM (jedną bazę danych) i na początku kilka aplikacji:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

… w ogóle można przenieść znacznie więcej, osiągając taki efekt:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

W Kubernetes uruchamiamy to wszystko jako oddzielne instancje, a to oznacza, że wciąż możemy mierzyć obciążenie i skalować je oddzielnie.

Podsumowując,

Spójrz na sytuację z szerszej perspektywy. Bardzo często wszystkie te problemy z mikroserwisami wynikają z tego, że ktoś wziął swoje zadanie, ale chciał „pobawić się w mikroserwisy”.

W słowie „mikroserwisy” część „mikro” jest zbędna.. Są „mikro” tylko dlatego, że są mniejsze od ogromnego monolitu. Ale nie myśl o nich jako o czymś małym.

A dla finalnej myśli wróćmy do pierwotnego wykresu:

Mikroserwisy: wielkość ma znaczenie, nawet jeśli masz Kubernetes

Przypis do niego (w prawym górnym rogu) sprowadza się do tego, że umiejętności zespołu, który realizuje Twój projekt, zawsze mają kluczowe znaczenie — właśnie one odegrają decydującą rolę w Twoim wyborze między mikroserwisami a monolitem. Jeśli zespół nie ma wystarczających umiejętności, ale zaczyna robić mikroserwisy, historia z pewnością zakończy się katastrofą.

Wideo i slajdy

Wideo z wystąpienia (~50 minut; niestety, nie oddaje ono licznych emocji odwiedzających, co w dużej mierze kształtowało nastrój prezentacji, ale takie jest życie):

Odtwarzaj wideo

Prezentacja wystąpienia:

P.S.

Inne wystąpienia w naszym blogu:

Prawdopodobnie zainteresują Cię również następujące publikacje:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster