Wzorce odporności aplikacji
Napiwek
Ta zawartość jest fragmentem książki eBook, Architekting Cloud Native .NET Applications for Azure, dostępnej na platformie .NET Docs lub jako bezpłatny plik PDF do pobrania, który można odczytać w trybie offline.
Pierwsza linia obrony to odporność aplikacji.
Chociaż możesz zainwestować dużo czasu na pisanie własnej struktury odporności, takie produkty już istnieją. Polly to kompleksowa biblioteka odporności platformy .NET i obsługa błędów przejściowych, która umożliwia deweloperom wyrażanie zasad odporności w sposób płynny i bezpieczny wątkowo. Aplikacja Polly jest przeznaczona dla aplikacji utworzonych przy użyciu programu .NET Framework lub .NET 7. W poniższej tabeli opisano funkcje odporności o nazwie policies
, dostępne w bibliotece Polly. Można je stosować pojedynczo lub grupować razem.
Zasady | Środowisko |
---|---|
Ponów próbę | Konfiguruje operacje ponawiania prób dla wyznaczonych operacji. |
Wyłącznik | Blokuje żądane operacje dla wstępnie zdefiniowanego okresu, gdy błędy przekraczają skonfigurowany próg |
Timeout | Określa limit czasu trwania, przez który obiekt wywołujący może czekać na odpowiedź. |
Gródź | Ogranicza akcje do puli zasobów o stałym rozmiarze, aby zapobiec niepowodzeniom wywołań z zasób. |
Pamięć podręczna | Automatycznie przechowuje odpowiedzi. |
Temat rezerwowy | Definiuje zachowanie strukturalne po awarii. |
Zwróć uwagę, jak na poprzedniej ilustracji zasady odporności dotyczą żądań komunikatów pochodzących z zewnętrznego klienta lub usługi zaplecza. Celem jest zrekompensowanie żądania usługi, która może być chwilowo niedostępna. Te krótkotrwałe przerwy zwykle manifestują się przy użyciu kodów stanu HTTP przedstawionych w poniższej tabeli.
Kod stanu HTTP | Przyczyna |
---|---|
404 | Nie znaleziono |
408 | Przekroczono limit czasu żądania |
429 | Zbyt wiele żądań (najprawdopodobniej zostało ograniczonych) |
502 | Zła brama |
503 | Usługa niedostępna |
504 | Limit czasu bramy |
Pytanie: Czy ponowisz próbę kodu stanu HTTP 403 — Zabronione? L.p. W tym miejscu system działa prawidłowo, ale informuje obiekt wywołujący, że nie ma autoryzacji do wykonania żądanej operacji. Należy zachować ostrożność, aby ponowić próbę wykonania tylko tych operacji spowodowanych awariami.
Zgodnie z zaleceniami w rozdziale 1 deweloperzy firmy Microsoft tworzący aplikacje natywne dla chmury powinni kierować do platformy .NET. W wersji 2.1 wprowadzono bibliotekę HTTPClientFactory służącą do tworzenia wystąpień klienta HTTP na potrzeby interakcji z zasobami opartymi na adresach URL. Zastępowanie oryginalnej klasy HTTPClient, klasa fabryki obsługuje wiele rozszerzonych funkcji, z których jedna jest ścisłą integracją z biblioteką odporności Polly. Dzięki niemu można łatwo zdefiniować zasady odporności w klasie uruchamiania aplikacji w celu obsługi częściowych awarii i problemów z łącznością.
Następnie rozszerzmy wzorce ponawiania prób i wyłącznika.
Wzorzec ponawiania
W rozproszonym środowisku natywnym dla chmury wywołania usług i zasobów w chmurze mogą zakończyć się niepowodzeniem z powodu przejściowych (krótkotrwałych) awarii, które zwykle korygują się po krótkim czasie. Zaimplementowanie strategii ponawiania prób pomaga usłudze natywnej dla chmury ograniczyć te scenariusze.
Wzorzec ponawiania umożliwia usłudze ponowienie próby wykonania operacji żądania, która zakończyła się niepowodzeniem (konfigurowalna) liczbą razy z wykładniczo rosnącym czasem oczekiwania. Rysunek 6–2 przedstawia ponowienie próby w akcji.
Rysunek 6–2. Wzorzec ponawiania próby w działaniu
Na poprzednim rysunku zaimplementowano wzorzec ponawiania dla operacji żądania. Jest on skonfigurowany tak, aby umożliwić maksymalnie cztery ponawianie prób przed niepowodzeniem z interwałem wycofywania (czas oczekiwania) rozpoczynającym się od dwóch sekund, co wykładniczo podwaja się dla każdej kolejnej próby.
- Pierwsze wywołanie kończy się niepowodzeniem i zwraca kod stanu HTTP 500. Aplikacja czeka na dwie sekundy i ponawia próbę wywołania.
- Drugie wywołanie również kończy się niepowodzeniem i zwraca kod stanu HTTP 500. Aplikacja podwoi teraz interwał wycofywania do czterech sekund i ponawia próbę wywołania.
- Na koniec trzecie wywołanie powiedzie się.
- W tym scenariuszu operacja ponawiania prób próbowałaby wykonać do czterech ponownych prób podczas podwojenia czasu trwania wycofywania przed niepowodzeniem wywołania.
- Gdyby 4. próba ponawiania nie powiodła się, zostanie wywołana zasada powrotu, aby bezpiecznie poradzić sobie z problemem.
Ważne jest, aby zwiększyć okres wycofywania przed ponowną próbą wywołania, aby umożliwić samodzielne poprawianie czasu usługi. Najlepszym rozwiązaniem jest zaimplementowanie wykładniczo rosnącego wycofywania (podwojenie okresu ponawiania próby) w celu umożliwienia odpowiedniego czasu korekty.
Wzorzec wyłącznika
Chociaż wzorzec ponawiania prób może pomóc uratować żądanie splątane w częściowym błędzie, istnieją sytuacje, w których awarie mogą być spowodowane przez nieprzewidziane zdarzenia, które będą wymagać dłuższych okresów czasu do rozwiązania. Takie błędy mogą mieć różny stopień ważności — od częściowej utraty łączności do całkowitej awarii usługi. W takich sytuacjach nie ma sensu, aby aplikacja stale ponawiała próbę wykonania operacji, która prawdopodobnie nie powiedzie się.
Co gorsza, wykonywanie ciągłych operacji ponawiania prób w usłudze niereponsywnej może spowodować przejście do scenariusza samodzielnej odmowy usługi, w którym usługa jest zalana ciągłymi wywołaniami wyczerpującymi zasobami, takimi jak pamięć, wątki i połączenia bazy danych, powodując awarię niepowiązanych części systemu, które korzystają z tych samych zasobów.
W takich sytuacjach preferowane byłoby natychmiastowe niepowodzenie operacji i próba wywołania usługi tylko wtedy, gdy prawdopodobnie powiedzie się.
Wzorzec wyłącznika może uniemożliwić aplikacji wielokrotne wykonywanie operacji, która prawdopodobnie zakończy się niepowodzeniem. Po wstępnie zdefiniowanej liczbie wywołań zakończonych niepowodzeniem blokuje cały ruch do usługi. Okresowo umożliwia wywołanie wersji próbnej w celu ustalenia, czy usterka została rozwiązana. Rysunek 6–3 przedstawia wzorzec wyłącznika w działaniu.
Rysunek 6–3. Wzorzec wyłącznika w działaniu
Na poprzedniej ilustracji do oryginalnego wzorca ponawiania prób dodano wzorzec wyłącznika. Zwróć uwagę, jak po 100 żądaniach, które zakończyły się niepowodzeniem, wyłącznik otwiera się i nie zezwala już na wywołania usługi. Wartość CheckCircuit ustawiona na 30 sekund określa, jak często biblioteka zezwala na przejście do usługi przez jedno żądanie. Jeśli to wywołanie powiedzie się, obwód zostanie zamknięty, a usługa będzie po raz kolejny dostępna dla ruchu.
Należy pamiętać, że intencja wzorca wyłącznika różni się od wzorca ponawiania. Wzorzec ponawiania umożliwia aplikacji ponawianie próby wykonania operacji w oczekiwaniu, że zakończy się powodzeniem. Wzorzec wyłącznika uniemożliwia aplikacji wykonywanie operacji, która może zakończyć się niepowodzeniem. Zazwyczaj aplikacja łączy te dwa wzorce przy użyciu wzorca ponawiania w celu wywołania operacji za pośrednictwem wyłącznika.
Testowanie pod kątem odporności
Testowanie odporności nie zawsze może odbywać się w taki sam sposób, w jaki testujesz funkcjonalność aplikacji (uruchamiając testy jednostkowe, testy integracji itd.). Zamiast tego należy przetestować sposób działania kompleksowego obciążenia w warunkach awarii, które występują tylko sporadycznie. Na przykład: wprowadzanie błędów przez awarie procesów, wygasłych certyfikatów, niedostępność usług zależnych itp. Struktury takie jak chaos-monkey mogą być używane do takich testów chaosu.
Odporność aplikacji jest koniecznością obsługi problematycznych żądanych operacji. Ale to tylko połowa historii. Następnie omówimy funkcje odporności dostępne w chmurze platformy Azure.