Elementy składowe aplikacji rozproszonych. Przybliżenie zerowe

Elementy składowe aplikacji rozproszonych. Przybliżenie zerowe

Świat nie stoi w miejscu. Postęp stwarza nowe wyzwania technologiczne. Zgodnie ze zmieniającymi się wymaganiami architektura systemów informatycznych musi ewoluować. Dzisiaj porozmawiamy o architekturze sterowanej zdarzeniami, współbieżności, współbieżności, asynchronii i o tym, jak można z tym spokojnie żyć w Erlangu.

Wprowadzenie

W zależności od wielkości projektowanego systemu i stawianych mu wymagań my, programiści, wybieramy sposób wymiany informacji w systemie. W większości przypadków, aby zorganizować interakcję usług, działającą opcją może być schemat z brokerem, na przykład oparty na RabbitMQ lub kafce. Czasem jednak przepływ zdarzeń, SLA i poziom kontroli nad systemem są takie, że gotowe komunikaty nie są dla nas odpowiednie. Oczywiście można trochę skomplikować system biorąc odpowiedzialność za warstwę transportową i tworzenie klastrów, na przykład stosując ZeroMQ lub nanomsg. Jeśli jednak system ma wystarczającą przepustowość i możliwości standardowego klastra Erlang, to kwestia wprowadzenia dodatkowego podmiotu wymaga szczegółowych badań i uzasadnienia ekonomicznego.

Temat reaktywnych aplikacji rozproszonych jest dość szeroki. Aby zachować formę artykułu, przedmiotem dzisiejszej dyskusji będą wyłącznie jednorodne środowiska zbudowane w oparciu o Erlang/Elixir. Ekosystem Erlang/OTP pozwala na wdrożenie architektury reaktywnej przy najmniejszym wysiłku. Ale w każdym razie będziemy potrzebować warstwy przesyłania wiadomości.

Podstawy teoretyczne

Projektowanie rozpoczyna się od zdefiniowania celów i ograniczeń. Główny cel nie leży w obszarze rozwoju dla samego rozwoju. Musimy pozyskać bezpieczne i skalowalne narzędzie, w oparciu o które będziemy mogli tworzyć i co najważniejsze rozwijać nowoczesne aplikacje na różnym poziomie: począwszy od aplikacji jednoserwerowych obsługujących małą grupę odbiorców, które później mogą rozwinąć się w klastry liczące nawet do 50 -60 węzłów, kończąc na federacjach klastrów. Zatem głównym celem jest maksymalizacja zysków poprzez zmniejszenie kosztów rozwoju i własności finalnego systemu.

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

  • Сzorientowany na wydarzenie.
    System jest zawsze gotowy do przejścia przez strumień zdarzeń i wykonania niezbędnych działań;
  • Мskalowalność.
    Poszczególne bloki można skalować zarówno w pionie, jak i w poziomie. Cały system musi być zdolny do nieskończonego wzrostu poziomego;
  • Оtolerancja błędów.
    Wszystkie poziomy i wszystkie usługi powinny mieć możliwość automatycznego odtwarzania po awariach;
  • Гgwarantowany czas reakcji.
    Czas jest cenny i użytkownicy nie powinni czekać zbyt długo.

Pamiętacie starą bajkę o „Małym silniku, który mógł”? Aby projektowany system pomyślnie opuścił fazę prototypu i był progresywny, jego fundament musi spełniać minimalne wymagania SMOG.

Do przesyłania wiadomości jako narzędzia infrastruktury i podstawy wszystkich usług dodaje się jeszcze jeden punkt: łatwość obsługi dla programistów.

Zorientowany na wydarzenia

Aby aplikacja mogła rozrosnąć się z pojedynczego serwera do klastra, jej architektura musi obsługiwać luźne łączenie. Model asynchroniczny spełnia ten wymóg. W nim nadawca i odbiorca dbają o ładunek informacyjny wiadomości i nie martwią się o transmisję i routing w systemie.

Skalowalność

Skalowalność i wydajność systemu idą obok siebie. Komponenty aplikacji muszą być w stanie wykorzystać wszystkie dostępne zasoby. Im efektywniej potrafimy wykorzystać moce produkcyjne i im bardziej optymalne są nasze metody przetwarzania, tym mniej pieniędzy wydajemy na sprzęt.

W ramach jednej maszyny Erlang tworzy wysoce konkurencyjne środowisko. Równowagę między współbieżnością a równoległością można ustawić, wybierając liczbę wątków systemu operacyjnego dostępnych dla maszyny wirtualnej Erlang i liczbę programów planujących wykorzystujących te wątki.
Procesy Erlanga nie współdzielą stanu i działają w trybie nieblokującym. Zapewnia to stosunkowo niskie opóźnienia i wyższą przepustowość w porównaniu z tradycyjnymi aplikacjami opartymi na blokowaniu. Harmonogram Erlanga zapewnia sprawiedliwą alokację procesora i IO, a brak blokowania pozwala aplikacji reagować nawet podczas szczytowych obciążeń lub awarii.

Na poziomie klastra występuje również problem utylizacji. Ważne jest, aby wszystkie maszyny w klastrze były równomiernie obciążone, a sieć nie była przeciążona. Wyobraźmy sobie sytuację: ruch użytkowników ląduje na przychodzących balanserach (haproxy, nginx itp.), rozdzielają one żądania przetwarzania możliwie równomiernie pomiędzy zestawem dostępnych backendów. W infrastrukturze aplikacji usługa wdrażająca wymagany interfejs jest dopiero na ostatnim etapie i będzie musiała zażądać szeregu innych usług, aby odpowiedzieć na początkowe żądanie. Żądania wewnętrzne wymagają również routingu i równoważenia.
Aby skutecznie zarządzać przepływami danych, przesyłanie wiadomości musi zapewniać programistom interfejs do zarządzania routingiem i równoważeniem obciążenia. Dzięki temu programiści będą mogli, wykorzystując wzorce mikrousług (agregator, proxy, łańcuch, oddział itp.), rozwiązywać zarówno standardowe problemy, jak i te, które rzadko się pojawiają.

Z biznesowego punktu widzenia skalowalność jest jednym z narzędzi zarządzania ryzykiem. Najważniejsze jest zaspokojenie życzeń klientów poprzez optymalne wykorzystanie sprzętu:

  • Gdy moc sprzętu wzrasta w wyniku postępu. Nie będzie bezczynny ze względu na niedoskonałe oprogramowanie. Erlang dobrze skaluje się w pionie i zawsze będzie w stanie wykorzystać wszystkie rdzenie procesora i dostępną pamięć;
  • W środowiskach chmurowych możemy zarządzać ilością sprzętu w zależności od aktualnego lub przewidywanego obciążenia i zagwarantować SLA.

tolerancja błędów

Rozważmy dwa aksjomaty: „Niepowodzenia są niedopuszczalne” i „Zawsze będą niepowodzenia”. Dla firmy awaria oprogramowania oznacza utratę pieniędzy i, co gorsza, utratę reputacji. Często można znaleźć kompromis pomiędzy możliwymi stratami a kosztem opracowania oprogramowania odpornego na błędy.

W perspektywie krótkoterminowej architektura uwzględniająca odporność na awarie pozwala zaoszczędzić pieniądze na zakupie gotowych rozwiązań klastrowych. Są drogie i mają też błędy.
W dłuższej perspektywie architektura odporna na błędy zwraca się wielokrotnie na wszystkich etapach rozwoju.
Przesyłanie komunikatów w obrębie bazy kodu pozwala na szczegółowe omówienie interakcji komponentów w systemie już na etapie rozwoju. Upraszcza to zadanie reagowania i zarządzania awariami, ponieważ wszystkie krytyczne komponenty radzą sobie z awariami, a powstały system wie, jak automatycznie powrócić do normalnego działania po awarii zgodnej z projektem.

Reakcja na coś

Niezależnie od awarii aplikacja musi odpowiadać na żądania i spełniać warunki SLA. Rzeczywistość jest taka, że ​​ludzie nie chcą czekać, więc firmy muszą się odpowiednio dostosować. Oczekuje się, że coraz więcej aplikacji będzie wysoce responsywnych.
Responsywne aplikacje działają w czasie zbliżonym do rzeczywistego. Erlang VM działa w miękkim trybie czasu rzeczywistego. W niektórych obszarach, takich jak handel akcjami, medycyna i kontrola urządzeń przemysłowych, ważny jest twardy tryb czasu rzeczywistego.
Systemy responsywne poprawiają UX i przynoszą korzyści biznesowi.

Wstępne podsumowanie

Planując ten artykuł, chciałem podzielić się swoim doświadczeniem w tworzeniu brokera przesyłania wiadomości i budowaniu w jego oparciu złożonych systemów. Część teoretyczno-motywacyjna okazała się jednak dość obszerna.
W drugiej części artykułu opowiem o niuansach wdrażania punktów wymiany, schematach przesyłania wiadomości i ich zastosowaniu.
W trzeciej części rozważymy ogólne zagadnienia organizacji usług, routingu i bilansowania. Porozmawiajmy o praktycznej stronie skalowalności i odporności na awarie systemów.

Koniec pierwszej części.

Strzał Fotek @lucabravo.

Źródło: www.habr.com

Dodaj komentarz