Najlepsze rozwiązania dotyczące obsługi błędów przejściowych

Wszystkie aplikacje komunikujące się z usługami zdalnymi i zasobami muszą wykrywać i odzyskiwać dane po błędach przejściowych. To wymaganie dotyczy szczególnie aplikacji uruchamianych w chmurze. Ze względu na charakter środowiska chmury i łączności przez Internet aplikacja prawdopodobnie częściej napotyka błędy przejściowe. Przejściowe błędy obejmują chwilową utratę łączności sieciowej ze składnikami i usługami, tymczasową niedostępność usługi i przekroczenia limitu czasu, które występują, gdy usługa jest zajęta. Te błędy zwykle są rozwiązywane bez interwencji, więc akcja może zakończyć się powodzeniem, jeśli aplikacja ponawia próbę po odpowiednim opóźnieniu.

Obsługa błędów przejściowych jest kluczową techniką odporności w ramach filaru niezawodności platformy Azure Well-Architected Framework. Jeśli wykryjesz i odzyskasz dane po przejściowych błędach na poziomie aplikacji, zmniejszysz prawdopodobieństwo kaskadowych awarii, które mogą powodować szerszą odpowiedź na zdarzenia lub procedury odzyskiwania po awarii . Efektywna obsługa błędów przejściowych pomaga obciążeniu tolerować rutynowe zakłócenia i utrzymywać dostępność bez eskalacji do procedur odzyskiwania na poziomie infrastruktury.

Dlaczego błędy przejściowe występują w chmurze?

Błędy przejściowe mogą wystąpić w dowolnym środowisku, na dowolnej platformie lub w systemie operacyjnym i w dowolnej aplikacji. W przypadku rozwiązań, które działają w infrastrukturze lokalnej, nadmiarowy sprzęt zwykle utrzymuje wydajność i dostępność aplikacji i jej składników. Składniki i zasoby znajdują się również blisko siebie. Takie podejście sprawia, że awaria jest mniej prawdopodobna, ale nadal mogą wystąpić błędy przejściowe. Nieoczekiwane zdarzenia, takie jak problemy z zasilaniem zewnętrznym lub siecią lub inne scenariusze awarii, mogą powodować awarie. Nadmiarowy sprzęt może być również kosztowny i często jest niedostatecznie używany.

Środowiska w chmurze mogą zapewnić wyższą ogólną dostępność, ponieważ dystrybuują obciążenia na wielu serwerach i używają nadmiarowości, automatycznego trybu failover i dynamicznej alokacji zasobów. Jednak charakter środowisk chmury sprawia, że błędy przejściowe są bardziej prawdopodobne z kilku powodów:

  • Wiele zasobów w środowisku chmury jest współużytkowanych, a dostęp do tych zasobów podlega ograniczaniu w celu ochrony zasobów. Niektóre usługi odrzucają połączenia, gdy obciążenie osiągnie określony poziom lub maksymalną szybkość przepływności. Takie podejście umożliwia usłudze przetwarzanie istniejących żądań i utrzymanie wydajności dla wszystkich użytkowników. Ograniczanie przepustowości pomaga utrzymać jakość usług dla sąsiadów i innych najemców, którzy korzystają ze współdzielonego zasobu.

  • Środowiska chmurowe używają dużej liczby standardowych jednostek sprzętowych. Zapewniają one wydajność dzięki dynamicznej dystrybucji obciążenia między wieloma jednostkami obliczeniowymi i składnikami infrastruktury. Zapewniają one niezawodność przez automatyczne przetwarzanie lub zastępowanie uszkodzonych jednostek. Ze względu na ten dynamiczny charakter błędy przejściowe i tymczasowe błędy połączenia mogą czasami wystąpić.

  • Więcej składników sprzętowych, w tym infrastruktury sieciowej, takich jak routery i moduły równoważenia obciążenia, często istnieją między aplikacją a zasobami i usługami, których używa. Ta infrastruktura może czasami wprowadzać dodatkowe opóźnienia połączenia i przejściowe błędy połączenia.

  • Warunki sieciowe między klientem a serwerem często się różnią, szczególnie w przypadku komunikacji przez Internet. Nawet w lokalizacjach lokalnych obciążenia o dużym natężeniu ruchu mogą spowalniać komunikację i powodować sporadyczne błędy połączeń.

Wyzwania

Błędy przejściowe mogą znacząco wpływać na postrzeganą dostępność aplikacji, nawet jeśli testujesz ją dokładnie w oczekiwanych warunkach. Aby zapewnić niezawodne działanie aplikacji hostowanych w chmurze, muszą one sprostać następującym wyzwaniom:

  • Aplikacja musi mieć możliwość wykrywania błędów w momencie ich wystąpienia i określenia, czy błędy są przejściowe, długotrwałe lub awarie terminalowe. Różne zasoby zwykle zwracają różne odpowiedzi w przypadku wystąpienia błędu. Odpowiedzi te mogą się również różnić w zależności od kontekstu operacji. Na przykład odpowiedź na błąd, gdy aplikacja odczytuje z magazynu, może się różnić od odpowiedzi na błąd podczas zapisywania w magazynie.

    Wiele zasobów i usług ma dobrze udokumentowane kontrakty dotyczące awarii przejściowych. Gdy te informacje nie są dostępne, znacznie trudniej jest określić charakter błędu i to, czy może to być przejściowe.

  • Aplikacja musi mieć możliwość ponawiania próby wykonania operacji, jeśli ustali, że błąd prawdopodobnie będzie przejściowy. Musi również śledzić liczbę ponownych prób wykonania operacji.

  • Aplikacja musi używać strategii ponawiania, która spełnia wymagania. Strategia określa, ile razy aplikacja powinna ponowić próbę, opóźnienie między próbami i akcje do wykonania po nieudanej próbie. Liczba prób i opóźnienie między nimi są często trudne do określenia. Strategia zależy od typu zasobu i bieżących warunków operacyjnych zasobu i aplikacji.

Ogólne wytyczne

Poniższe wskazówki mogą pomóc w projektowaniu odpowiednich mechanizmów obsługi błędów przejściowych dla aplikacji.

Sprawdzanie, czy istnieje wbudowany mechanizm ponawiania prób

Wiele usług udostępnia zestaw SDK lub bibliotekę klienta, która zawiera mechanizm obsługi błędów przejściowych. Zasady ponawiania, które są używane, są zwykle dostosowane do charakteru i wymagań usługi docelowej. Alternatywnie interfejsy REST dla usług mogą zwracać informacje, które mogą pomóc w ustaleniu, czy jest wymagana ponowna próba i jak długo czekać przed następną próbą.

Użyj wbudowanego mechanizmu ponawiania, gdy jest dostępna wbudowana opcja, chyba że masz określone i dobrze zrozumiałe wymagania, które sprawiają, że inne zachowanie ponawiania jest bardziej odpowiednie dla danego scenariusza.

Usługi platformy Azure obsługują błędy przejściowe inaczej. Niektóre usługi udostępniają zasady ponawiania na poziomie zestawu SDK, które obejmują konfigurowalne algorytmy wycofywania. Inne usługi udostępniają funkcje platformy, takie jak sondy kondycji i limity czasu widoczności, które uzupełniają logikę ponawiania prób na poziomie aplikacji. Zapoznaj się z przewodnikiem dotyczącym niezawodności dla każdej używanej usługi platformy Azure. Te przewodniki obejmują dedykowaną sekcję, która zawiera zalecenia specyficzne dla usługi dotyczące konfiguracji ponawiania prób, dostrajania limitu czasu i monitorowania kondycji.

Sprawdzanie, czy ponawianie próby pasuje do operacji

Powtarzaj zadania tylko wtedy, gdy błędy są przejściowe, co zazwyczaj wskazuje charakter błędu, oraz gdy ponowne wykonanie operacji może zakończyć się powodzeniem. W przypadku usług opartych na protokole HTTP kod stanu 429 (zbyt wiele żądań) i błędy serwera 5xx są typowymi kandydatami ponawiania prób. Większość błędów klienta 4xx, takich jak 400, 401, 403 i 404, wskazuje problemy, które nie zostaną rozwiązane. Nie ponawiaj próby wykonania zadań, które próbują wykonać operację, która nie może zakończyć się powodzeniem, na przykład aktualizacja bazy danych do elementu, który nie istnieje, lub żądanie do usługi lub zasobu, który napotkał błąd krytyczny.

Ogólnie rzecz biorąc, zaimplementuj ponawianie prób tylko wtedy, gdy można określić ich pełny efekt i kiedy rozumiesz i można zweryfikować warunki. W przeciwnym razie niech wywołujący kod zajmie się ponawianiem prób. Błędy zwracane z zasobów i usług spoza kontroli mogą ewoluować wraz z upływem czasu i może być konieczne ponowne przejrzenie logiki wykrywania błędów przejściowych.

Podczas tworzenia usług lub składników zaimplementuj kody błędów i komunikaty, które ułatwiają klientom określenie, czy należy ponowić próbę wykonania operacji, które zakończyły się niepowodzeniem. Na przykład zwróć wartość isTransient, aby wskazać, czy klient powinien powtórzyć operację, i zasugerować odpowiednie opóźnienie przed kolejną próbą. Tworząc usługę internetową, zwracaj niestandardowe błędy zdefiniowane przez kontrakty usług. Klienci ogólne mogą nie być w stanie odczytać tych błędów, ale są one przydatne podczas tworzenia niestandardowych klientów.

Określanie odpowiedniej liczby ponownych prób i interwału

Zoptymalizuj liczbę ponownych prób i interwał dla typu przypadku użycia. Jeśli nie spróbujesz wystarczająco dużo razy, aplikacja nie może ukończyć operacji i zakończy się niepowodzeniem. Jeśli ponowisz próbę zbyt wiele razy lub nie zaczekasz wystarczająco długo między próbami, aplikacja może przechowywać zasoby, takie jak wątki, połączenia i pamięć przez długi czas, co niekorzystnie wpływa na kondycję aplikacji. Aby uzyskać więcej informacji, zobacz Wzorzec ponawiania prób.

Dostosuj wartości interwału czasu i liczbę ponownych prób wykonania operacji. Jeśli na przykład operacja jest częścią interakcji użytkownika, interwał powinien być krótki i należy spróbować tylko kilku ponownych prób. Użyj tego podejścia, aby uniknąć oczekiwania użytkowników na odpowiedź, która przechowuje otwarte połączenia i może zmniejszyć dostępność dla innych użytkowników. Jeśli operacja jest częścią długotrwałego lub krytycznego przepływu pracy, w którym anulowanie i ponowne uruchomienie procesu jest kosztowne lub czasochłonne, możesz poczekać dłużej między próbami i ponowić próbę więcej razy.

Określenie prawidłowych interwałów między ponownymi próbami jest najtrudniejszą częścią projektowania udanej strategii. Typowe strategie używają następujących typów interwału ponawiania prób:

  • Wycofywanie wykładnicze: Aplikacja czeka chwilę przed pierwszą ponowną próbą, a następnie wykładniczo zwiększa czas między poszczególnymi kolejnymi ponownymi próbami. Na przykład może ponowić próbę wykonania operacji po dwóch sekundach, czterech sekundach, ośmiu sekundach i do określonej liczby prób lub łącznego czasu trwania. Dodaj jitter, czyli małe losowe opóźnienie, do każdego interwału ponawiania prób, aby zapobiec synchronizowaniu ponownych prób przez wielu klientów i tworzeniu skoków obciążenia na docelowej usłudze.

  • Interwały przyrostowe: Aplikacja czeka chwilę przed pierwszą ponowną próbą, a następnie przyrostowo zwiększa czas między kolejnymi ponownymi próbami. Na przykład może ponowić próbę wykonania operacji po 3 sekundach, 7 sekundach i 11 sekundach.

  • Interwały regularne: Aplikacja czeka przez ten sam okres między poszczególnymi próbami. Na przykład może ponowić próbę wykonania operacji co trzy sekundy.

  • Natychmiastowe ponowienie próby: Przejściowe błędy spowodowane przez zdarzenia, takie jak kolizje pakietów sieciowych lub nagłe skoki w komponentach sprzętowych, są zazwyczaj krótkotrwałe. W tych scenariuszach natychmiastowe ponawianie próby wykonania operacji może pomóc, ponieważ może się to powieść, jeśli błąd zostanie usunięty w czasie potrzebnym aplikacji do złożenia i wysłania następnego żądania. Nie próbuj więcej niż jednego natychmiastowego ponawiania próby. Jeśli natychmiastowe ponawianie nie powiedzie się, przełącz się do alternatywnych strategii, takich jak wycofywanie wykładnicze lub akcje rezerwowe.

  • Randomizacja: Każda z wymienionych wcześniej strategii ponawiania może obejmować randomizację, aby zapobiec wysyłaniu kolejnych prób przez wiele instancji klienta w tym samym czasie. Na przykład jedno wystąpienie może ponowić próbę wykonania operacji po 3 sekundach, 11 sekundach lub 28 sekundach, podczas gdy inne wystąpienie może ponowić próbę wykonania operacji po 4 sekundach, 12 sekundach lub 26 sekundach. Randomizacja to przydatna technika, którą można połączyć z innymi strategiami.

Używaj strategii wykładniczego cofania z losowymi opóźnieniami dla operacji w tle i stosuj strategie ponawiania prób bezpośrednich lub w regularnych odstępach dla operacji interakcyjnych. W obu przypadkach wybierz opóźnienie i liczbę ponownych prób, aby maksymalne opóźnienie dla wszystkich ponownych prób spełniało wymaganie całkowitego opóźnienia.

Kombinacja czynników przyczynia się do ogólnego maksymalnego czasu limitu dla operacji ponawianej. Rozważmy następujący czynniki:

  • Czas potrzebny na wygenerowanie odpowiedzi po nieudanym połączeniu. Wartość limitu czasu w kliencie zazwyczaj ustawia tę godzinę.

  • Opóźnienie między ponownymi próbami.

  • Maksymalna liczba ponownych prób.

Suma tych czasów może spowodować długie ogólne czasy operacji, zwłaszcza w przypadku korzystania ze strategii opóźnienia wykładniczego, w której interwał między ponawiania próbami szybko rośnie po każdym niepowodzeniu. Jeśli proces musi spełniać określony cel poziomu obsługi (SLO), całkowity czas operacji, w tym wszelkie timeouty i opóźnienia, musi mieścić się w granicach zdefiniowanych w celu SLO.

Rozważ limit czasu operacji przy wyborze interwałów ponawiania prób, aby uniknąć natychmiastowego rozpoczęcia kolejnej próby, na przykład jeśli okres limitu czasu jest podobny do interwału ponawiania prób. Ustal, czy chcesz zachować łączny możliwy okres, czyli limit czasu oraz interwały ponawiania prób, w ramach określonego progu całkowitego czasu. Jeśli operacja ma wyjątkowo krótki lub długi limit czasu, limit czasu może mieć wpływ na czas oczekiwania i częstotliwość ponawiania próby wykonania operacji.

Ustaw limity czasu dla każdego wywołania wychodzącego przed zaimplementowaniem logiki ponawiania prób. Limity czasu, ponawianie prób i metody wycofywania współpracują ze sobą. Strategia ponawiania prób jest tak skuteczna, jak czas oczekiwania, który reguluje poszczególne próby. Zbyt długie czasy oczekiwania podczas przestojów powodują nagromadzenie wątków i połączeń. Przekroczenia limitu czasu, które są zbyt krótkie, powodują przedwczesne niepowodzenia operacji, które w przeciwnym razie powiedzie się.

Nie implementuj nadmiernie agresywnych strategii ponawiania prób. Te strategie używają interwałów zbyt krótkich lub ponownych prób, które występują zbyt często. Mogą one niekorzystnie wpłynąć na docelowy zasób lub usługę. Mogą one również uniemożliwić odzyskanie zasobu lub usługi, więc zasób lub usługa nadal blokują lub odrzucają żądania. W tym scenariuszu jest tworzony cykl, w którym aplikacja wysyła więcej żądań do zasobu lub usługi, co dodatkowo zmniejsza możliwość odzyskiwania.

Użyj typu wyjątku i wszelkich danych, które zawiera, lub kodów błędów i komunikatów zwracanych przez usługę, aby zoptymalizować liczbę ponownych prób i interwał między nimi. Niektóre wyjątki lub kody błędów, takie jak HTTP 503 (usługa niedostępna), mogą wskazywać, że usługa nie powiodła się i nie odpowie na dalsze próby. Gdy odpowiedź zawiera nagłówek Retry-After, postępuj zgodnie z nim i poczekaj co najmniej określony czas przed następną próbą. Ten sygnał dostarczony przez serwer odzwierciedla harmonogram odzyskiwania usługi i ma pierwszeństwo przed obliczeniami zmniejszania obciążenia po stronie klienta.

Użyj metody kolejki martwych listów, aby informacje z żądania przychodzącego nie były tracone po użyciu wszystkich ponownych prób. Technika ta odkłada niepowodzenia do późniejszego przetworzenia zamiast je odrzucać.

Unikaj antywzorców

W większości przypadków unikaj implementacji zawierających zduplikowane warstwy kodu ponawiania prób. Unikaj projektów korzystających z kaskadowych mechanizmów ponawiania prób lub stosujących ponawianie prób na każdym etapie operacji, która obejmuje hierarchię żądań, chyba że masz określone wymagania. W takich wyjątkowych przypadkach należy użyć zasad, które ograniczają liczbę ponownych prób i okresów opóźnień, i upewnij się, że rozumiesz konsekwencje.

Rozważmy na przykład jeden składnik, który wysyła żądanie do innej, a następnie uzyskuje dostęp do usługi docelowej. Ponowne próby, gdzie każde z dwóch wywołań jest wykonywane trzykrotnie, dają łącznie dziewięć prób dla usługi.

Wiele usług i zasobów implementuje wbudowany mechanizm ponawiania prób. Wyłącz lub zmodyfikuj te mechanizmy, jeśli musisz zaimplementować ponawianie prób na wyższym poziomie. Aby uzyskać więcej informacji na temat ryzyka nieskoordynowanych ponownych prób, zobacz Antywzorzec Retry Storm.

Nigdy nie implementuj niekończącego się mechanizmu ponawiania prób. Takie podejście zwykle uniemożliwia odzyskiwanie zasobów lub usługi po sytuacjach przeciążenia i powoduje ograniczanie przepustowości i odrzucanie połączeń przez dłuższy czas. Użyj skończonej liczby ponownych prób lub zaimplementuj wzorzec, taki jak wyłącznik, aby umożliwić usłudze powrót do działania.

Zaimplementuj budżet ponawiania prób, aby ograniczyć łączną liczbę ponownych prób we wszystkich żądaniach w ramach procesu lub usługi oprócz limitów dla każdego pojedynczego żądania. Na przykład można zezwolić procesowi na nie więcej niż 60 ponownych prób na minutę względem określonej zależności. Jeśli wyczerpiesz budżet, zakończ żądanie niepowodzeniem natychmiast zamiast ponawiania.

Limity ponawiania prób dla poszczególnych żądań nie mogą zapobiec scenariuszowi, w którym wiele współbieżnych żądań jest ponawianych kilka razy, co w rezultacie przeciąża niewydolną usługę podrzędną. Budżet na ponowne próby ogranicza zagregowane obciążenie ponowień i może stanowić różnicę między zlokalizowanym problemem z wydajnością a awarią kaskadową.

Nigdy nie należy wykonywać natychmiastowych ponownych prób więcej niż raz.

Unikaj regularnego interwału ponawiania prób podczas uzyskiwania dostępu do usług i zasobów na platformie Azure, zwłaszcza w przypadku dużej liczby ponownych prób. Najlepszym podejściem w tym scenariuszu jest strategia wycofywania wykładniczego, która korzysta z możliwości przerywania obwodu.

Uniemożliwiaj jednoczesne wysyłanie ponownych prób przez wiele instancji tego samego klienta lub przez wiele instancji różnych klientów. Jeśli ten scenariusz jest prawdopodobny, należy wprowadzić losowość do interwałów ponawiania prób.

Testowanie strategii i implementacji ponawiania prób

Przetestuj strategię ponawiania prób w szerokim zakresie warunków, zwłaszcza gdy aplikacja i jej docelowe zasoby lub usługi działają pod ekstremalnym obciążeniem. Aby sprawdzić zachowanie podczas testowania, możesz wykonać następujące czynności:

  • Uwzględnij przejściowe błędy w praktykach inżynierii chaosu i iniekcji błędów , celowo wprowadzając je do środowiska nieprodukcyjnego i produkcyjnego. Na przykład wysyłaj nieobsługiwane żądania lub dodaj kod, który wykrywa żądania testowe i odpowiada różnymi typami błędów.

  • Utwórz pozorną wersję zasobu lub usługi, która zwraca zakres błędów, które może zwrócić rzeczywista usługa. Upewnij się, że obejmuje wszystkie typy błędów wykryte przez strategię ponawiania prób.

  • W przypadku usług niestandardowych, które tworzysz i wdrażasz, wymuszaj przejściowe błędy poprzez tymczasowe wyłączenie usługi lub przeciążenie usługi. Nie próbuj przeciążyć żadnych zasobów udostępnionych ani usług udostępnionych na platformie Azure.

  • Rozważ użycie usługi iniekcji błędów do uruchamiania kontrolowanych eksperymentów względem zasobów platformy Azure. Na przykład Azure Chaos Studio obsługuje bezpośrednie błędy usługowe, takie jak dodawanie opóźnienia sieci lub ponowne uruchamianie klastra pamięci podręcznej oraz błędy agentowe, takie jak wywieranie presji na pamięć lub kończenie procesu na maszynie wirtualnej (VM). Eksperymenty iniekcji błędów można zintegrować z potokami ciągłej integracji i ciągłego dostarczania (CI/CD), aby stale weryfikować odporność w ramach procesu wdrażania.

  • W przypadku interfejsów API opartych na protokole HTTP rozważ użycie biblioteki w automatyzacji testów, aby zmienić wynik żądań HTTP, wydłużając czas podróży danej wiadomości lub zmieniając odpowiedź, na przykład kod stanu HTTP, nagłówki, treść wiadomości lub inne elementy. Takie podejście ułatwia deterministyczne testowanie podzestawu warunków awarii dla błędów przejściowych i innych typów błędów.

  • Uruchom testy współbieżne i o wysokim współczynniku obciążenia, aby upewnić się, że mechanizm ponawiania i strategia działają prawidłowo w tych warunkach. Te testy pomagają również potwierdzić, że próby ponawiania nie wpływają na operacje klientów ani nie powodują skażenia krzyżowego między żądaniami.

Zarządzanie konfiguracjami zasad ponawiania prób

Polityka ponawiania to połączenie wszystkich elementów twojej strategii ponawiania. Definiuje mechanizm wykrywania, który określa następujące czynniki:

  • Czy błąd może być przejściowy
  • Rodzaj interwału do zastosowania, taki jak regularny, wykładnicze cofanie lub losowe
  • Rzeczywiste wartości interwału
  • Liczba ponownych prób

Zaimplementuj ponawianie prób w wielu miejscach, w tym w aplikacjach podstawowych i w każdej warstwie bardziej złożonych aplikacji. Zamiast trwale kodować elementy zasad w wielu lokalizacjach, użyj centralnego punktu do przechowywania wszystkich zasad. Na przykład przechowuj wartości, takie jak interwał i liczba ponownych prób w plikach konfiguracyjnych aplikacji. Odczytaj je w czasie wykonywania i zbuduj programowo zasady ponawiania prób. Takie podejście upraszcza zarządzanie ustawieniami oraz modyfikowanie i dostrajanie wartości w celu reagowania na zmieniające się wymagania i scenariusze. Zaprojektuj system do przechowywania wartości, a nie ponownego odczytania pliku konfiguracji dla każdego żądania, i użyj odpowiednich wartości domyślnych, jeśli konfiguracja nie udostępnia wartości.

Przechowuj wartości używane do tworzenia zasad ponawiania w czasie wykonywania w systemie konfiguracji aplikacji, aby można je było zmienić bez konieczności ponownego uruchamiania aplikacji.

Skorzystaj z wbudowanych lub domyślnych strategii ponawiania dostępnych w używanych interfejsach API klienta, ale tylko wtedy, gdy są one odpowiednie dla danego scenariusza. Te strategie są zazwyczaj ogólne. Mogą one być odpowiednie w niektórych scenariuszach, ale w innych scenariuszach nie zapewniają pełnego zakresu opcji spełniających określone wymagania. Aby określić najbardziej odpowiednie wartości, przetestuj, aby zrozumieć, jak ustawienia wpływają na aplikację. Aby zapoznać się z domyślnymi zasadami ponawiania i opcjami konfiguracji specyficznymi dla usługi, zapoznaj się z przewodnikiem dotyczącym niezawodności dla każdej usługi platformy Azure w Twojej architekturze.

Rejestrowanie i śledzenie przejściowych i nietransientnych błędów

Strategia ponawiania prób powinna obejmować obsługę wyjątków i inną instrumentację, która rejestruje próby ponawiania prób. Sporadyczny błąd przejściowy i ponowienie próby są oczekiwane i nie wskazują problemu. Jednak regularna lub rosnąca liczba ponownych prób zwykle wskazuje problem, który może spowodować awarię lub zmniejszyć wydajność i dostępność aplikacji.

Rejestruj błędy przejściowe jako wpisy ostrzegawcze, a nie jako wpisy błędów, aby systemy monitorowania nie wykrywały ich jako błędów aplikacji, które mogą wyzwalać fałszywe alerty.

Zapisz wartość w wpisach dziennika, która wskazuje, czy ograniczanie w usłudze lub innych typach błędów, jak na przykład błędy połączeń, spowodowują ponawianie prób. Takie podejście pomaga rozróżniać przyczyny podczas analizy danych. Wzrost błędów ograniczania przepustowości zwykle wskazuje na wadę projektu w aplikacji lub potrzebę migracji do usługi Premium, która zapewnia dedykowany sprzęt.

Zmierz i zarejestruj ogólny czas, który upłynął dla operacji obejmujących mechanizm ponawiania prób. Ta metryka dokładnie wskazuje ogólny wpływ błędów przejściowych na czasy odpowiedzi użytkownika, opóźnienie procesu i wydajność przypadków użycia aplikacji. Zarejestruj liczbę ponownych prób, aby zrozumieć czynniki, które przyczyniają się do czasu odpowiedzi.

Zaimplementuj system telemetrii i monitorowania, który zgłasza alerty w przypadku zwiększenia następujących metryk:

  • Liczba i szybkość awarii
  • Średnia liczba ponownych prób
  • Całkowity czas, który upłynął przed powodzeniem operacji

Zarządzanie operacjami, które stale kończą się niepowodzeniem

Utwórz plan obsługi operacji, które nadal kończą się niepowodzeniem przy każdej próbie. Takie sytuacje są nieuniknione.

  • Strategia ponawiania określa maksymalną liczbę ponownych prób wykonania operacji przez aplikację. Nie uniemożliwia aplikacji powtórzenia operacji, aby rozpocząć od tej samej liczby ponownych prób. Na przykład, jeśli usługa przetwarzania zamówień zakończy się niepowodzeniem z powodu błędu krytycznego, który trwałe usunie ją z usługi, strategia ponawiania może wykrywać przekroczenie limitu czasu połączenia i traktować je jako błąd przejściowy. Kod ponawia próbę operacji określoną liczbę razy, a następnie zatrzymuje. Gdy inny klient zleci zamówienie, aplikacja spróbuje wykonać operację ponownie, ponowi próbę i zakończy się niepowodzeniem.

  • Aby zapobiec ciągłym ponawianiu prób dla operacji, które stale kończą się niepowodzeniem, zaimplementuj wzorzec przerywacza obwodu. Jeśli używasz tego wzorca, jeśli liczba niepowodzeń w określonym przedziale czasu przekracza próg, żądania są zwracane do obiektu wywołującego natychmiast jako błędy, a aplikacja nie próbuje uzyskać dostępu do zasobu lub usługi, która zakończyła się niepowodzeniem.

  • Aplikacja może okresowo testować usługę sporadycznie i z długimi interwałami między żądaniami, aby wykryć, kiedy stanie się dostępna. Interwał zależy od czynników, takich jak krytyczność operacji i charakter usługi. Może to potrwać od kilku minut do kilku godzin. Po pomyślnym zakończeniu testu aplikacja może wznowić normalne operacje i przekazać żądania do nowo odzyskanej usługi.

  • W międzyczasie może być możliwe powrót do innego wystąpienia usługi w innym centrum danych lub aplikacji. Możesz również użyć podobnej usługi zapewniającej zgodność, ale prostszą, funkcjonalność lub wykonać pewne alternatywne operacje na podstawie nadziei, że usługa jest dostępna wkrótce. Możesz na przykład przechowywać żądania dotyczące usługi w kolejce lub magazynie danych i próbować ponownie później. Możesz też przekierować użytkownika do alternatywnego wystąpienia aplikacji, obniżając jej wydajność, ale wciąż zapewniając akceptowalną funkcjonalność, lub po prostu przesłać komunikat użytkownikowi, informując, że aplikacja nie jest obecnie dostępna.

Inne zagadnienia

Podczas określania wartości liczby ponownych prób i interwałów ponawiania prób dla zasad należy rozważyć, czy operacja w usłudze lub zasobie jest częścią długotrwałej lub wieloetapowej operacji. Może to być trudne lub kosztowne, aby zrekompensować wszystkie kroki operacyjne, które już zakończyły się pomyślnie, gdy jeden z nich zakończy się niepowodzeniem. W takim przypadku długi interwał i duża liczba ponownych prób mogą być dopuszczalne, o ile strategia nie blokuje innych operacji przez przechowywanie lub blokowanie ograniczonych zasobów.

Zastanów się, czy ponawianie próby wykonania tej samej operacji może spowodować niespójności danych. Jeśli aplikacja powtarza części wieloetapowego procesu, a operacje nie są idempotentne, mogą wystąpić niespójności. Jeśli na przykład operacja, która zwiększa wartość, powtarza się, generuje niepoprawny wynik. Powtarzana operacja, która wysyła komunikat do kolejki, może również powodować problemy dla użytkownika, który nie może wykryć zduplikowanych komunikatów. Aby zapobiec tym scenariuszom, należy zaprojektować każdy krok jako operację idempotentną. Aby uzyskać więcej informacji, zobacz Wzorce idempotentności.

Należy starannie określić zakres operacji, które aplikacja ponawia. Na przykład może być łatwiej zaimplementować logikę ponawiania prób na poziomie obejmującym kilka operacji i ponowić próbę wykonania wszystkich z nich w przypadku awarii. Jednak takie podejście może prowadzić do problemów z idempotencją lub niepotrzebnych operacji wycofywania.

Jeśli wybierzesz zakres ponawiania, który obejmuje kilka operacji, uwzględnij całkowite opóźnienie wszystkich z nich podczas określania interwałów ponawiania próby, podczas monitorowania czasu, który upłynął operacji, i przed zgłaszaniem alertów dotyczących błędów.

Zapoznaj się ze sposobem, w jaki strategia ponawiania prób ma wpływ na sąsiadów i innych dzierżawców w aplikacji udostępnionej oraz w przypadku korzystania z udostępnionych zasobów i usług. Agresywne zasady ponawiania prób mogą zwiększyć liczbę przejściowych błędów występujących dla innych użytkowników i aplikacji, które współużytkujące zasoby i usługi. Zasady ponawiania, które implementują inni użytkownicy, mogą również mieć wpływ na aplikację. W przypadku aplikacji o znaczeniu krytycznym dla działania firmy należy używać usług Premium, które nie są udostępniane. Takie podejście umożliwia kontrolowanie obciążenia i ograniczania przepustowości zasobów i usług, co może uzasadniać dodatkowe koszty.

Następny krok