Bloki budowlane aplikacji rozproszonych. Zerowe podejście

Bloki budowlane aplikacji rozproszonych. Zerowe podejście

Świat nie stoi w miejscu. Postęp stawia przed nami nowe technologiczne wyzwania. W odpowiedzi na zmieniające się wymagania, także architektura systemów informacyjnych musi ewoluować. Dziś porozmawiamy o architekturze opartej na zdarzeniach, konkurencyjności, równoległości, asynchroniczności i o tym, jak w Erlang można pokojowo z tym wszystkim współżyć.

Wprowadzenie

W zależności od rozmiarów projektowanego systemu i jego wymagań, my, programiści, wybieramy sposób wymiany informacji w systemie. W większości przypadków, aby zorganizować interakcję usług, roboczym rozwiązaniem może być schemat z brokerem, na przykład oparty na RabbitMQ lub Kafka. Jednak czasami strumień zdarzeń, SLA i poziom kontroli nad systemem są takie, że gotowe rozwiązania do komunikacji nie będą odpowiednie. Oczywiście można nieco skomplikować system, biorąc na siebie odpowiedzialność za poziom transportu i tworzenie klastra, na przykład używając ZeroMQ lub nanomsg. Ale jeśli system ma wystarczającą przepustowość i możliwości standardowego klastra Erlanga, wówczas wprowadzenie dodatkowej jednostki wymaga szczegółowego zbadania i uzasadnienia ekonomicznego.

Temat reaktywnych aplikacji rozproszonych jest dość obszerny. Aby zmieścić się w formacie artykułu, przedmiotem dzisiejszej dyskusji będą tylko homogeniczne środowiska zbudowane na bazie Erlang/Elixir. Ekosystem Erlang/OTP pozwala na wdrożenie architektury reaktywnej przy minimalnym nakładzie pracy. Jednak w każdym przypadku potrzebować będziemy warstwy wymiany wiadomości.

Podstawy teoretyczne

Projektowanie rozpoczyna się od określenia celów i ograniczeń. Głównym celem nie jest rozwój dla samego rozwoju. Musimy stworzyć bezpieczne i skalowalne narzędzie, na bazie którego można budować, a co najważniejsze – rozwijać nowoczesne aplikacje różnego poziomu: zaczynając od jednoserwerowych, obsługujących niewielką publiczność, które w przyszłości mogą przekształcić się w klastry do 50-60 węzłów, aż po federacje klastrów. W ten sposób głównym celem jest maksymalizacja zysku poprzez zmniejszenie kosztów budowy i posiadania końcowego systemu.

Wyróżnijmy 4 główne wymagania dotyczące końcowego systemu:

  • Zorientacja na zdarzenia.
    System zawsze jest gotowy do przepuszczania przez siebie strumienia zdarzeń i podejmowania niezbędnych działań;
  • Mskalowalność.
    Poszczególne bloki mogą skalować się zarówno pionowo, jak i poziomo. Cały system powinien mieć zdolność do nieskończonego wzrostu poziomego;
  • oodporność na awarie.
    Wszystkie poziomy i wszystkie usługi powinny mieć możliwość automatycznego przywracania po awariach;
  • Gwarantowany czas reakcji.
    Czas jest cenny, a użytkownicy nie powinni czekać zbyt długo.

Pamiętasz starą bajkę o „The little engine that could”, znanej jako „Pociąg, który mógł”? Aby projektowany system skutecznie przeszedł z etapu prototypu do progresywnego rozwiązania, jego fundament musi spełniać minimalne wymagania. MOGŁO.

Do messaging jako infrastrukturalnego narzędzia i podstawy dla wszystkich usług dodawany jest jeszcze jeden punkt: wygoda użytkowania dla programistów.

orientacja na zdarzenia

Aby aplikacja mogła wyrosnąć z jednego serwera do klastra, jej architektura musi zapewniać luźną powiązanie. Temu wymaganiu odpowiada asynchroniczny model. W nim nadawca i odbiorca dbają o ładunek informacyjny wiadomości i nie martwią się o przesyłanie oraz routowanie w systemie.

Skalowalność

Skalowalność i efektywność systemu idą w parze. Komponenty aplikacji powinny umieć wykorzystywać wszystkie dostępne zasoby. Im skuteczniej możemy wykorzystywać moce wytwórcze i im optymalniejsze są nasze metody przetwarzania, tym mniej wydajemy pieniędzy na sprzęt.

W ramach jednego maszyny Erlang tworzy środowisko o wysokiej konkurencyjności. Równowagę między konkurencyjnością a równoległością można ustawić, wybierając liczbę wątków systemu operacyjnego dostępnych dla Erlang VM i liczbę planistów wykorzystujących te wątki.
Procesy Erlang nie mają wspólnego stanu i działają w trybie nieblokującym. Zapewnia to stosunkowo niską latencję i wyższą przepustowość niż tradycyjne aplikacje oparte na blokującej synchronizacji. Planista Erlang dba o sprawiedliwy podział CPU i IO, a brak blokad pozwala aplikacji odpowiadać nawet w trybie szczytowym lub w przypadku awarii.

Na poziomie klastra problem z wykorzystaniem również istnieje. Ważne jest, aby wszystkie maszyny w klastrze były równomiernie obciążone, a sieć nieprzeciążona. Wyobraźmy sobie sytuację: ruch użytkowników jest kierowany do zewnętrznych load balancerów (haproxy, nginx, itd.), które maksymalnie równomiernie rozdzielają zapytania do przetworzenia pomiędzy zestaw dostępnych backendów. W ramach infrastruktury aplikacji usługa, która realizuje wymagany interfejs, to tylko ostatnia mila, i będzie musiała zażądać od szeregu innych usług, aby odpowiedzieć na początkowe zapytanie. Wewnętrzne zapytania również wymagają routingu i równoważenia obciążenia.
Aby efektywnie zarządzać przepływem danych, messaging musi zapewnić deweloperom interfejs do zarządzania routowaniem i rozdzielaniem obciążenia. Dzięki temu deweloperzy będą mogli, korzystając ze wzorców mikroserwisowych (agregator, proxy, łańcuch, rozgałęzienie, itp.), rozwiązywać zarówno standardowe zadania, jak i te występujące rzadko.

Z perspektywy biznesowej skalowalność to jeden z narzędzi zarządzania ryzykiem. Najważniejsze to zaspokoić potrzeby klientów, optymalnie wykorzystując sprzęt:

  • Przy zwiększeniu mocy sprzętu w wyniku postępu. Nie będzie on stał bezczynnie z powodu niedoskonałości oprogramowania. Erlang doskonale skaluje się w pionie i zawsze będzie w stanie wykorzystać wszystkie rdzenie CPU oraz dostępną pamięć;
  • W warunkach chmurowych możemy zarządzać ilością sprzętu w zależności od bieżącego lub prognozowanego obciążenia i gwarantować SLA.

Odporność na awarie

Rozważmy dwie aksjomat: „Awaria jest niedopuszczalna” i „Awaria zawsze się zdarzy”. Dla biznesu awaria oprogramowania to utrata pieniędzy, a co gorsza – reputacji. Balansując pomiędzy możliwymi stratami a kosztami rozwoju oprogramowania odpornego na awarie, często można znaleźć kompromis.

W krótkim okresie architektura, w której zakłada się odporność na awarie, oszczędza pieniądze na zakup gotowych rozwiązań do klasteryzacji. Są one drogie i również zawierają błędy.
W długim okresie architektura odporna na awarie wielokrotnie zwraca koszty jej zastosowania na wszystkich etapach rozwoju.
Komunikacja w kodzie jest nadal w fazie rozwoju, co pozwala na szczegółowe zaplanowanie interakcji komponentów w systemie. Ułatwia to zadanie reagowania i zarządzania awariami, ponieważ wszystkie odpowiedzialne komponenty zajmują się awariami, a końcowy system wie, jak automatycznie powrócić do normalnego stanu po awarii projektowanej z myślą o tym.

Reaktywność

Bez względu na awarie, aplikacja musi odpowiadać na zapytania i spełniać SLA. Rzeczywistość jest taka, że ludzie nie chcą czekać, dlatego biznes musi się dostosować. Coraz więcej aplikacji oczekuje dużej reaktywności.
Reaktywne aplikacje działają w trybie zbliżonym do rzeczywistego czasu. Erlang VM funkcjonuje w trybie miękkiego czasu rzeczywistego. W niektórych dziedzinach, takich jak handel giełdowy, medycyna, zarządzanie sprzętem przemysłowym, ważny jest tryb twardego czasu rzeczywistego.
Reaktywne systemy poprawiają UX i są korzystne dla biznesu.

Wstępny podsumowanie

Planując ten artykuł, chciałem podzielić się doświadczeniem stworzenia brokera wymiany komunikatów i zbudowania na jego podstawie złożonych systemów. Ale część teoretyczna i motywacyjna okazała się dosyć obszerna.
W drugiej części artykułu opowiem o niuansach realizacji punktów wymiany, wzorach wymiany komunikatów i ich zastosowaniu.
W trzeciej części omówimy ogólne kwestie organizacji usług, trasowania i równoważenia obciążenia. Porozmawiamy o praktycznych aspektach skalowalności i odporności na awarie systemów.

Koniec pierwszej części.

Zdjęcie @lucabravo.

Ź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