Obsługa częściowej awarii
Napiwek
Ta zawartość jest fragmentem książki eBook, architektury mikrousług platformy .NET dla konteneryzowanych aplikacji platformy .NET dostępnych na platformie .NET Docs lub jako bezpłatnego pliku PDF, który można odczytać w trybie offline.
W systemach rozproszonych, takich jak aplikacje oparte na mikrousługach, istnieje stale obecne ryzyko częściowej awarii. Na przykład pojedyncza mikrousługa/kontener może zakończyć się niepowodzeniem lub może nie być dostępna do odpowiadania przez krótki czas albo jedna maszyna wirtualna lub serwer mogą ulec awarii. Ponieważ klienci i usługi są oddzielnymi procesami, usługa może nie odpowiadać w odpowiednim czasie na żądanie klienta. Usługa może być przeciążona i odpowiadać bardzo wolno na żądania lub po prostu nie być dostępna przez krótki czas z powodu problemów z siecią.
Rozważmy na przykład stronę Szczegóły zamówienia z przykładowej aplikacji eShopOnContainers. Jeśli mikrousługa porządkowania nie odpowiada, gdy użytkownik próbuje przesłać zamówienie, nieprawidłowa implementacja procesu klienta (aplikacja internetowa MVC) — na przykład jeśli kod klienta miał używać synchronicznych kontrolerów RPCs bez limitu czasu — blokowałby wątki w nieskończoność oczekujące na odpowiedź. Oprócz tworzenia złego środowiska użytkownika każda nieodpowiadcza oczekiwanie zużywa lub blokuje wątek, a wątki są niezwykle cenne w wysoce skalowalnych aplikacjach. Jeśli istnieje wiele zablokowanych wątków, w końcu środowisko uruchomieniowe aplikacji może zabrakło wątków. W takim przypadku aplikacja może stać się globalnie nie odpowiada zamiast częściowo nie odpowiadać, jak pokazano na rysunku 8-1.
Rysunek 8–1. Częściowe błędy z powodu zależności, które wpływają na dostępność wątku usługi
W dużej aplikacji opartej na mikrousługach wszelkie częściowe awarie mogą zostać wzmocnione, zwłaszcza jeśli większość wewnętrznych interakcji mikrousług jest oparta na synchronicznych wywołaniach HTTP (co jest uważane za antywzór). Pomyśl o systemie, który odbiera miliony połączeń przychodzących dziennie. Jeśli system ma zły projekt oparty na długich łańcuchach synchronicznych wywołań HTTP, te wywołania przychodzące mogą spowodować powstanie wielu milionów wywołań wychodzących (załóżmy, że stosunek 1:4) do kilkudziesięciu wewnętrznych mikrousług jako zależności synchronicznych. Ta sytuacja jest pokazana na rysunku 8–2, zwłaszcza zależności nr 3, która uruchamia łańcuch, wywołując zależność 4, która następnie wywołuje #5.
Rysunek 8–2. Wpływ nieprawidłowego projektu z długimi łańcuchami żądań HTTP
Sporadycznie awaria jest gwarantowana w rozproszonym i opartym na chmurze systemie, nawet jeśli każda zależność ma doskonałą dostępność. To fakt, który należy wziąć pod uwagę.
Jeśli nie projektujesz i implementujesz technik w celu zapewnienia odporności na uszkodzenia, nawet małe przestoje mogą być wzmocnione. Na przykład 50 zależności z 99,99% dostępności spowodowałoby kilka godzin przestoju każdego miesiąca z powodu tego efektu tętnienia. Gdy zależność mikrousługi kończy się niepowodzeniem podczas obsługi dużej liczby żądań, awaria może szybko saturacji wszystkich dostępnych wątków żądań w każdej usłudze i awarii całej aplikacji.
Rysunek 8–3. Częściowa awaria wzmocniona przez mikrousługi z długimi łańcuchami synchronicznych wywołań HTTP
Aby zminimalizować ten problem, w sekcji Asynchroniczna integracja mikrousług wymusza autonomię mikrousługi, ten przewodnik zachęca do korzystania z komunikacji asynchronicznej w ramach wewnętrznych mikrousług.
Ponadto niezbędne jest zaprojektowanie mikrousług i aplikacji klienckich w celu obsługi częściowych błędów — czyli tworzenia odpornych mikrousług i aplikacji klienckich.