Odporność aplikacji i infrastruktury

Ukończone

Odporność to możliwość odzyskiwania po awariach przejściowych. Strategia odzyskiwania aplikacji przywraca normalną funkcję z minimalnym wpływem na użytkownika. Awarie mogą wystąpić w środowiskach chmury, a aplikacja powinna reagować w taki sposób, aby zminimalizować przestoje i utratę danych. W idealnej sytuacji aplikacja bezproblemowo obsługuje błędy bez znajomości problemu przez użytkownika.

Ponieważ środowiska mikrousług mogą być niestabilne, projektuj aplikacje, aby oczekiwały częściowych awarii i obsługiwały je. Na przykład częściowa awaria może obejmować wyjątki kodu, awarie sieci, nieodpowiadania procesów serwera lub awarie sprzętu. Nawet planowane działania, takie jak przenoszenie kontenerów do innego węzła w klastrze Kubernetes, mogą spowodować przejściowy błąd.

Podejścia do odporności

W projektowaniu odpornych aplikacji często trzeba wybrać między szybkim wyłączeniem a stopniową degradacją. Szybkie niepowodzenie oznacza, że aplikacja natychmiast zgłosi błąd lub wyjątek, gdy coś pójdzie nie tak, zamiast próbować odzyskać lub obejść problem. Dzięki temu można szybko identyfikować i rozwiązywać problemy. Stopniowa degradacja oznacza, że aplikacja będzie starała się nadal działać w ograniczonym zakresie, nawet wtedy, gdy któryś ze składników ulegnie awarii.

W aplikacjach natywnych dla chmury ważne jest, aby usługi obsługiwały błędy w sposób płynny, a nie ulegały awarii szybko. Ponieważ mikrousługi są zdecentralizowane i niezależnie wdrażalne, oczekiwane są częściowe awarie. Szybkie niepowodzenie umożliwi awarii w jednej usłudze szybkie wyłączenie usług zależnych, co zmniejsza ogólną odporność systemu. Zamiast tego mikrousługi powinny być kodowane w celu przewidywania i tolerowania zarówno awarii usług wewnętrznych, jak i zewnętrznych. To łagodne obniżenie umożliwia całemu systemowi kontynuowanie działania, nawet jeśli niektóre usługi zostaną zakłócone. Krytyczne funkcje dostępne dla użytkowników mogą być trwałe, co pozwala uniknąć całkowitej awarii. Kontrolowana awaria umożliwia również zakłóconym usługom odzyskiwanie lub samoleczenie, zanim wpłyną na resztę systemu. Zatem dla aplikacji opartych na mikrousługach łagodna degradacja lepiej współgra z najlepszymi praktykami dotyczącymi odporności, takimi jak izolacja błędów i szybkie odzyskiwanie. Zapobiega to przekształceniu się lokalnych incydentów w kaskadę w całym systemie.

Istnieją dwa podstawowe podejścia do wspierania łagodnej degradacji z odpornością: dotyczące aplikacji i infrastruktury. Każde podejście ma zalety i wady. Oba podejścia mogą być odpowiednie w zależności od sytuacji. W tym module wyjaśniono, jak zaimplementować zarówno odporność opartą na kodzie , jak i na infrastrukturze .

Odporność oparta na kodzie

Aby zaimplementować odporność opartą na kodzie, platforma .NET ma bibliotekę rozszerzeń do obsługi odporności i przejściowych awarii, Microsoft.Extensions.Http.Resilience.

Używa płynnej, łatwej do zrozumienia składni do tworzenia kodu obsługującego błędy w bezpieczny wątkowo sposób. Istnieje kilka zasad odporności, które definiują zachowanie obsługi błędów. W tym module zastosujesz strategię ponowienia (Retry) oraz strategię obwodu przerywanego (Circuit Breaker) do operacji klienta HTTP.

Strategia ponawiania prób

Strategia Ponawianie próby jest dokładnie tym, co sugeruje nazwa. Żądanie jest ponawiane po krótkim oczekiwaniu, jeśli zostanie odebrana odpowiedź o błędzie. Czas oczekiwania wzrasta wraz z każdym ponowieniu próby. Wzrost może być liniowy lub wykładniczy.

Po osiągnięciu maksymalnej liczby ponownych prób strategia rezygnuje i zgłasza wyjątek. Z perspektywy użytkownika aplikacja zwykle trwa dłużej, aby wykonać niektóre operacje. Aplikacja może również zająć trochę czasu przed poinformowaniem użytkownika, że nie może ukończyć operacji.

Strategia wyłącznika

Strategia wyłącznika umożliwia usłudze docelowej odpoczynek po wielokrotnych awariach, poprzez wstrzymanie prób nawiązania z nią komunikacji. Usługa może mieć poważny problem i tymczasowo nie może odpowiedzieć. Po określonej liczbie kolejnych niepowodzeń próby połączenia zostają wstrzymane, dochodzi do otwarcia obwodu. Podczas tego oczekiwania dodatkowe operacje w usłudze docelowej natychmiast kończą się niepowodzeniem, nawet nie próbując nawiązać połączenia z usługą docelową. Po upływie czasu oczekiwania operacja zostanie podjęta ponownie. Jeśli usługa pomyślnie odpowie, obwód zostaje zamknięty, a system powraca do normalnego działania.

Odporność oparta na infrastrukturze

Aby zaimplementować odporność opartą na infrastrukturze, można użyć service mesh. Oprócz odporności bez zmieniania kodu siatka usług zapewnia zarządzanie ruchem, zasady, zabezpieczenia, silną tożsamość i możliwość obserwowania. Aplikacja jest oddzielona od tych funkcji operacyjnych, które są przenoszone do warstwy infrastruktury.

Porównanie z metodami opartymi na kodzie

Podejście odporności opartej na infrastrukturze może korzystać z widoku opartego na metrykach, który umożliwia dynamiczne dostosowywanie się do warunków klastra w czasie rzeczywistym. Takie podejście dodaje kolejny wymiar do zarządzania klastrem, ale nie dodaje żadnego kodu.

W przypadku podejścia opartego na kodzie:

  • Należy odgadnąć, które parametry ponawiania i przekroczenia limitu czasu są odpowiednie.
  • Skoncentruj się na konkretnym żądaniu HTTP.

Nie ma rozsądnego sposobu reagowania na awarię infrastruktury w kodzie aplikacji. Rozważmy setki lub tysiące żądań, które są przetwarzane jednocześnie. Nawet ponowienie próby z wykładniczym opóźnieniem proporcjonalnym do liczby ponowień może zalać usługę.

Z kolei podejścia oparte na infrastrukturze nie wiedzą o wewnętrznych aplikacjach. Na przykład złożone transakcje bazy danych są niewidoczne dla siatki usług. Takie transakcje mogą być chronione tylko przed awarią za pomocą podejścia opartego na kodzie.

W kolejnych lekcjach zaimplementujesz odporność aplikacji opartej na mikrousługach przy użyciu odporności protokołu HTTP platformy .NET w kodzie i siatki usługi Linkerd.