Udostępnij za pośrednictwem


Projekt aplikacji obciążeń o krytycznym znaczeniu na platformie Azure

Podczas projektowania aplikacji zarówno wymagania funkcjonalne, jak i niefunkcjonalne aplikacji mają kluczowe znaczenie. W tym obszarze projektowania opisano wzorce architektury i strategie skalowania, które mogą ułatwić odporność aplikacji na awarie.

Ważne

Ten artykuł jest częścią serii obciążeń Azure Well-Architected Framework o znaczeniu krytycznym. Jeśli nie znasz tej serii, zalecamy rozpoczęcie od tematu Co to jest obciążenie o krytycznym znaczeniu?

Architektura jednostki skalowania

Wszystkie aspekty funkcjonalne rozwiązania muszą być w stanie skalować, aby sprostać zmianom zapotrzebowania. Zalecamy użycie architektury jednostki skalowania w celu optymalizacji kompleksowej skalowalności poprzez przedziały, a także standaryzację procesu dodawania i usuwania pojemności. Jednostka skalowania to jednostka logiczna lub funkcja, którą można skalować niezależnie. Jednostka może składać się ze składników kodu, platform hostingu aplikacji, sygnatur wdrażania obejmujących powiązane składniki, a nawet subskrypcji do obsługi wymagań obejmujących wiele dzierżaw.

Zalecamy takie podejście, ponieważ dotyczy limitów skalowania poszczególnych zasobów i całej aplikacji. Pomaga to w przypadku złożonych scenariuszy wdrażania i aktualizacji, ponieważ jednostkę skalowania można wdrożyć jako jedną jednostkę. Ponadto można przetestować i zweryfikować określone wersje składników w lekcji przed kierowaniem do niego ruchu użytkowników.

Załóżmy, że Twoja aplikacja o znaczeniu krytycznym jest katalogiem produktów online. Ma przepływ użytkownika do przetwarzania komentarzy i ocen produktów. Przepływ używa interfejsów API do pobierania i publikowania komentarzy i ocen oraz składników pomocniczych, takich jak punkt końcowy OAuth, magazyn danych i kolejki komunikatów. Bezstanowe punkty końcowe interfejsu API reprezentują szczegółowe jednostki funkcjonalne, które muszą dostosowywać się do zmian na żądanie. Podstawowa platforma aplikacji musi być również w stanie odpowiednio skalować. Aby uniknąć wąskich gardeł wydajności, składniki podrzędne i zależności muszą być również skalowane do odpowiedniego stopnia. Mogą one być skalowane niezależnie, jako oddzielne jednostki skalowania lub razem w ramach jednej jednostki logicznej.

Przykładowe jednostki skalowania

Na poniższej ilustracji przedstawiono możliwe zakresy jednostek skalowania. Zakresy obejmują między zasobniki mikrousług a węzłami klastra i sygnaturami wdrożenia regionalnego.

Diagram przedstawiający wiele zakresów dla jednostek skalowania.

Uwagi dotyczące projektowania

  • Zakres. Zakres jednostki skalowania, relacja między jednostkami skalowania i ich składnikami powinna być zdefiniowana zgodnie z modelem pojemności. Weź pod uwagę wymagania niefunkcjonalne dotyczące wydajności.

  • Limity skalowania. Limity i przydziały skalowania subskrypcji platformy Azure mogą mieć wpływ na projektowanie aplikacji, wybory technologiczne i definicję jednostek skalowania. Jednostki skalowania mogą pomóc w obejściu limitów skalowania usługi. Jeśli na przykład klaster usługi AKS w jednej lekcji może mieć tylko 1000 węzłów, możesz użyć dwóch jednostek, aby zwiększyć ten limit do 2000 węzłów.

  • Oczekiwane obciążenie. Użyj liczby żądań dla każdego przepływu użytkownika, oczekiwanej szczytowej liczby żądań (żądań na sekundę) oraz wzorców ruchu dziennego/tygodniowego/sezonowego, aby poinformować o wymaganiach dotyczących skalowania rdzeni. Należy również uwzględnić oczekiwane wzorce wzrostu zarówno dla ruchu, jak i woluminu danych.

  • Akceptowalna obniżona wydajność. Ustal, czy obniżona wydajność usługi z wysokim czasem odpowiedzi jest akceptowalna pod obciążeniem. W przypadku modelowania wymaganej pojemności wymagana wydajność rozwiązania jest czynnikiem krytycznym.

  • Wymagania niefunkcjonalne. Scenariusze techniczne i biznesowe mają różne zagadnienia dotyczące odporności, dostępności, opóźnienia, pojemności i możliwości obserwowania. Przeanalizuj te wymagania w kontekście kluczowych przepływów użytkownika końcowego. Będziesz mieć względną elastyczność w zakresie projektowania, podejmowania decyzji i wyboru technologii na poziomie przepływu użytkownika.

Zalecenia dotyczące projektowania

  • Zdefiniuj zakres jednostki skalowania i limity, które będą wyzwalać jednostkę do skalowania.

  • Upewnij się, że wszystkie składniki aplikacji mogą być skalowane niezależnie lub w ramach jednostki skalowania, która zawiera inne powiązane składniki.

  • Zdefiniuj relację między jednostkami skalowania w oparciu o model pojemności i wymagania niefunkcjonalne.

  • Zdefiniuj sygnaturę wdrożenia regionalnego w celu ujednolicenia aprowizacji, zarządzania i obsługi zasobów aplikacji regionalnych w heterogenicznej, ale współzależnej jednostce skalowania. W miarę zwiększania obciążenia można wdrożyć dodatkowe sygnatury w tym samym regionie platformy Azure lub w różnych regionach, aby skalować rozwiązanie w poziomie.

  • Użyj subskrypcji platformy Azure jako jednostki skalowania, aby limity skalowania w ramach jednej subskrypcji nie ograniczały skalowalności. Takie podejście dotyczy scenariuszy aplikacji o dużej skali, które mają znaczny ruch.

  • Model wymagał pojemności wokół zidentyfikowanych wzorców ruchu, aby upewnić się, że wystarczająca pojemność jest aprowizowana w godzinach szczytu, aby zapobiec pogorszeniu usług. Alternatywnie zoptymalizuj pojemność poza godzinami szczytu.

  • Mierzenie czasu wymaganego do przeprowadzenia operacji skalowania w poziomie i skalowania w poziomie w celu zapewnienia, że naturalne zmiany ruchu nie powodują niedopuszczalnego poziomu degradacji usług. Śledzenie czasów trwania operacji skalowania jako metryki operacyjnej.

Uwaga

Podczas wdrażania w strefie docelowej platformy Azure upewnij się, że subskrypcja strefy docelowej jest przeznaczona dla aplikacji, aby zapewnić wyraźną granicę zarządzania i uniknąć antywzorzec hałaśliwego sąsiada.

Globalne rozproszenie

Nie można uniknąć awarii w każdym wysoce rozproszonym środowisku. Ta sekcja zawiera strategie ograniczania wielu scenariuszy błędów. Aplikacja musi być w stanie wytrzymać awarie regionalne i strefowe. Należy go wdrożyć w aktywnym/aktywnym modelu, aby obciążenie było dystrybuowane we wszystkich regionach.

Obejrzyj to wideo, aby zapoznać się z omówieniem planowania awarii w aplikacjach o krytycznym znaczeniu i zmaksymalizowania odporności:

Uwagi dotyczące projektowania

  • Nadmiarowość. Aplikacja musi zostać wdrożona w wielu regionach. Ponadto w obrębie regionu zdecydowanie zalecamy używanie stref dostępności w celu zapewnienia odporności na uszkodzenia na poziomie centrum danych. Strefy dostępności mają obwód opóźnienia mniejszy niż 2 milisekundy między strefami dostępności. W przypadku obciążeń ,które są "czatty" w różnych strefach, to opóźnienie może wprowadzić karę za wydajność transferu danych między strefami.

  • Model aktywny/aktywny. Zalecana jest strategia aktywnego/aktywnego wdrażania, ponieważ maksymalizuje dostępność i zapewnia wyższą złożoną umowę dotyczącą poziomu usług (SLA). Jednak może to powodować wyzwania związane z synchronizacją danych i spójnością w wielu scenariuszach aplikacji. Sprostanie wyzwaniom na poziomie platformy danych przy jednoczesnym uwzględnieniu kompromisów w zakresie zwiększonego kosztu i nakładu pracy inżynieryjnej.

    Aktywne/aktywne wdrożenie wielu dostawców usług w chmurze to sposób na potencjalnie ograniczenie zależności od zasobów globalnych w ramach jednego dostawcy usług w chmurze. Jednak wielochmurowa strategia wdrażania aktywnego/aktywnego wdrażania wprowadza znaczną złożoność wokół ciągłej integracji/ciągłego wdrażania. Ponadto, biorąc pod uwagę różnice w specyfikacji zasobów i możliwościach wśród dostawców usług w chmurze, potrzebne są wyspecjalizowane sygnatury wdrażania dla każdej chmury.

  • Rozkład geograficzny. Obciążenie może mieć wymagania dotyczące zgodności dotyczące przechowywania danych geograficznych, ochrony danych i przechowywania danych. Zastanów się, czy istnieją konkretne regiony, w których muszą znajdować się dane, czy też należy wdrożyć zasoby.

  • Zażądaj źródła. Bliskość geograficzna i gęstość użytkowników lub systemów zależnych powinny informować o decyzjach projektowych dotyczących globalnej dystrybucji.

  • Łączność. Sposób uzyskiwania dostępu do obciążenia przez użytkowników lub systemy zewnętrzne będzie mieć wpływ na projekt. Zastanów się, czy aplikacja jest dostępna za pośrednictwem publicznego Internetu, czy sieci prywatnych korzystających z sieci VPN lub obwodów usługi Azure ExpressRoute.

Aby uzyskać zalecenia projektowe i opcje konfiguracji na poziomie platformy, zobacz Application platform: Global distribution (Platforma aplikacji: dystrybucja globalna).

Luźno połączona architektura sterowana zdarzeniami

Sprzężenie umożliwia komunikację międzyusług za pośrednictwem dobrze zdefiniowanych interfejsów. Luźne sprzężenie umożliwia niezależne działanie składnika aplikacji. Styl architektury mikrousług jest zgodny z wymaganiami krytycznymi. Ułatwia wysoką dostępność, uniemożliwiając awarie kaskadowe.

W przypadku luźnego sprzężenia zdecydowanie zalecamy włączenie projektowania sterowanego zdarzeniami. Asynchroniczne przetwarzanie komunikatów za pośrednictwem pośrednika może tworzyć odporność.

Diagram ilustrujący asynchroniczną komunikację sterowaną zdarzeniami.

W niektórych scenariuszach aplikacje mogą łączyć luźne i ścisłe sprzężenia w zależności od celów biznesowych.

Uwagi dotyczące projektowania

  • Zależności środowiska uruchomieniowego. Luźno powiązane usługi nie powinny być ograniczone do korzystania z tej samej platformy obliczeniowej, języka programowania, środowiska uruchomieniowego lub systemu operacyjnego.

  • Skalowanie. Usługi powinny być w stanie skalować niezależnie. Optymalizowanie korzystania z infrastruktury i zasobów platformy.

  • Odporność na uszkodzenia. Błędy powinny być obsługiwane oddzielnie i nie powinny mieć wpływu na transakcje klientów.

  • Integralność transakcyjna. Rozważ efekt tworzenia i trwałości danych, który występuje w oddzielnych usługach.

  • Śledzenie rozproszone. Kompleksowe śledzenie może wymagać złożonej aranżacji.

Zalecenia dotyczące projektowania

  • Dopasuj granice mikrousług do krytycznych przepływów użytkownika.

  • Używaj komunikacji asynchronicznej opartej na zdarzeniach, jeśli jest to możliwe, aby obsługiwać zrównoważoną skalę i optymalną wydajność.

  • Użyj wzorców, takich jak Skrzynka odbiorcza i Sesja transakcyjna, aby zagwarantować spójność, tak aby każdy komunikat był przetwarzany poprawnie.

Przykład: Podejście oparte na zdarzeniach

Implementacja referencyjna Mission-Critical Online używa mikrousług do przetwarzania pojedynczej transakcji biznesowej. Stosuje operacje zapisu asynchronicznie z brokerem komunikatów i procesem roboczym. Operacje odczytu są synchroniczne, a wynik jest zwracany bezpośrednio do elementu wywołującego.

Diagram przedstawiający komunikację sterowaną zdarzeniami.

Wzorce odporności i obsługa błędów w kodzie aplikacji

Aplikacja o krytycznym znaczeniu musi być zaprojektowana tak, aby była odporna, tak aby obsługiwała jak najwięcej scenariuszy awarii. Ta odporność maksymalizuje dostępność i niezawodność usługi. Aplikacja powinna mieć możliwości samonaprawiania, które można zaimplementować przy użyciu wzorców projektowych, takich jak ponawianie prób z wycofywaniem i wyłącznikiem.

W przypadku niepowodzeń przejściowych, których nie można w pełni ograniczyć w logice aplikacji, model kondycji i otoki operacyjne muszą podjąć działania naprawcze. Kod aplikacji musi zawierać odpowiednie instrumentację i rejestrowanie, aby poinformować model kondycji i ułatwić późniejsze rozwiązywanie problemów lub analizę głównej przyczyny zgodnie z potrzebami. Należy zaimplementować śledzenie rozproszone, aby udostępnić obiekt wywołujący kompleksowy komunikat o błędzie zawierający identyfikator korelacji w przypadku wystąpienia błędu.

Narzędzia, takie jak Szczegółowe informacje aplikacji, mogą ułatwić wykonywanie zapytań, korelowanie i wizualizowanie śladów aplikacji.

Uwagi dotyczące projektowania

  • Prawidłowe konfiguracje. Nie jest niczym niezwykłym w przypadku przejściowych problemów, które powodują błędy kaskadowe. Na przykład ponów próbę bez odpowiedniego wycofywania zaostrza problem, gdy usługa jest ograniczana. Możesz przestrzeń ponawiania prób opóźniać liniowo lub zwiększać je wykładniczo, aby cofnąć się przez rosnące opóźnienia.

  • Punkty końcowe kondycji. Testy funkcjonalne można uwidocznić w kodzie aplikacji przy użyciu punktów końcowych kondycji, które zewnętrzne rozwiązania mogą sondować w celu pobrania stanu kondycji składnika aplikacji.

Zalecenia dotyczące projektowania

Oto kilka typowych wzorców inżynierii oprogramowania dla odpornych aplikacji:

Wzorzec Podsumowanie
Wyrównywanie obciążeń przy użyciu kolejki Wprowadza bufor między użytkownikami i żądanymi zasobami w celu zapewnienia spójnych poziomów obciążenia. Gdy żądania konsumentów są kolejkowane, proces roboczy obsługuje je względem żądanego zasobu w tempie ustawionym przez proces roboczy i przez zdolność żądanego zasobu do przetwarzania żądań. Jeśli konsumenci oczekują odpowiedzi na swoje żądania, musisz zaimplementować oddzielny mechanizm odpowiedzi. Zastosuj kolejność priorytetową, aby najważniejsze działania były wykonywane jako pierwsze.
Wyłącznik Zapewnia stabilność przez oczekiwanie na odzyskiwanie lub szybkie odrzucanie żądań zamiast blokowania podczas oczekiwania na niedostępną usługę zdalną lub zasób. Ten wzorzec obsługuje również błędy, które mogą zająć zmienną ilość czasu na odzyskanie sprawności po nawiązaniu połączenia z usługą zdalną lub zasobem.
Gródź Próbuje podzielić wystąpienia usługi na grupy na podstawie wymagań dotyczących obciążenia i dostępności, izolując niepowodzenia utrzymania funkcjonalności usługi.
Saga Zarządza spójnością danych między mikrousługami, które mają niezależne magazyny danych, zapewniając, że usługi aktualizują się nawzajem za pośrednictwem zdefiniowanych kanałów zdarzeń lub komunikatów. Każda usługa wykonuje transakcje lokalne w celu zaktualizowania własnego stanu i opublikowania zdarzenia w celu wyzwolenia następnej transakcji lokalnej w sagi. Jeśli aktualizacja usługi zakończy się niepowodzeniem, saga uruchamia transakcje wyrównywujące, aby przeciwdziałać poprzednim krokom aktualizacji usługi. Poszczególne kroki aktualizacji usługi mogą samodzielnie implementować wzorce odporności, takie jak ponawianie próby.
Monitorowanie punktu końcowego kondycji Implementuje kontrole funkcjonalne w aplikacji, do których narzędzia zewnętrzne mogą uzyskiwać dostęp za pośrednictwem uwidocznionych punktów końcowych w regularnych odstępach czasu. Odpowiedzi z punktów końcowych można interpretować przy użyciu kluczowych metryk operacyjnych w celu informowania o kondycji aplikacji i wyzwalaniu odpowiedzi operacyjnych, takich jak zgłaszanie alertu lub wykonywanie wdrożenia wycofywania wyrównacyjnego.
Ponów próbę Obsługuje błędy przejściowe elegancko i przezroczystie.
— Anuluj, jeśli błąd jest mało prawdopodobne, aby był przejściowy i jest mało prawdopodobne, aby zakończyć się powodzeniem, jeśli operacja zostanie podjęta ponownie.
— Spróbuj ponownie, jeśli błąd jest nietypowy lub rzadki, a operacja prawdopodobnie powiedzie się, jeśli spróbujesz ponownie natychmiast.
— Ponów próbę po opóźnieniu, jeśli przyczyną błędu jest warunek, który może wymagać krótkiego czasu na odzyskanie, takich jak łączność sieciowa lub awarie o dużym obciążeniu. Zastosuj odpowiednią strategię wycofywania w miarę wzrostu opóźnień ponawiania prób.
Ograniczanie przepływności Steruje zużyciem zasobów używanych przez składniki aplikacji, co chroni je przed nadmiernym obciążeniami. Gdy zasób osiągnie próg obciążenia, odchyla operacje o niższym priorytcie i obniża poziom nieistotnych funkcji, tak aby podstawowe funkcje mogły być kontynuowane do momentu, aż wystarczające zasoby będą dostępne do powrotu do normalnego działania.

Poniżej przedstawiono kilka dodatkowych zaleceń:

  • Użyj zestawów SDK dostarczonych przez dostawcę, takich jak zestawy SDK platformy Azure, aby nawiązać połączenie z usługami zależnych. Używaj wbudowanych funkcji odporności zamiast implementowania niestandardowych funkcji.

  • Zastosuj odpowiednią strategię wycofywania podczas ponawiania próby wywołań zależności, które zakończyły się niepowodzeniem, aby uniknąć scenariusza ataków DDoS z własnymi zadaniami.

  • Zdefiniuj typowe kryteria inżynieryjne dla wszystkich zespołów mikrousług aplikacji, aby zwiększyć spójność i szybkość korzystania z wzorców odporności na poziomie aplikacji.

  • Zaimplementuj wzorce odporności przy użyciu sprawdzonych ustandaryzowanych pakietów, takich jak Polly dla języka C# lub Sentinel dla języka Java.

  • Użyj identyfikatorów korelacji dla wszystkich zdarzeń śledzenia i komunikatów dziennika, aby połączyć je z danym żądaniem. Zwraca identyfikatory korelacji do elementu wywołującego dla wszystkich wywołań, a nie tylko żądań niepomyślnie.

  • Użyj rejestrowania strukturalnego dla wszystkich komunikatów dziennika. Wybierz ujednolicony ujście danych operacyjnych dla śladów aplikacji, metryk i dzienników, aby umożliwić operatorom łatwe debugowanie problemów. Aby uzyskać więcej informacji, zobacz Zbieranie, agregowanie i przechowywanie danych monitorowania dla aplikacji w chmurze.

  • Upewnij się, że dane operacyjne są używane razem z wymaganiami biznesowymi, aby poinformować model kondycji aplikacji.

Wybór języka programowania

Ważne jest, aby wybrać odpowiednie języki programowania i struktury. Te decyzje są często oparte na zestawach umiejętności lub standardowych technologiach w organizacji. Jednak ważne jest, aby ocenić wydajność, odporność i ogólne możliwości różnych języków i struktur.

Uwagi dotyczące projektowania

  • Możliwości zestawu programistycznego. Istnieją różnice w możliwościach oferowanych przez zestawy SDK usług platformy Azure w różnych językach. Te różnice mogą mieć wpływ na wybór usługi platformy Azure lub języka programowania. Jeśli na przykład usługa Azure Cosmos DB jest opcją wykonalną, język Go może nie być odpowiednim językiem programowania, ponieważ nie ma zestawu SDK innej firmy.

  • Aktualizacje funkcji. Zastanów się, jak często zestaw SDK jest aktualizowany przy użyciu nowych funkcji dla wybranego języka. Często używane zestawy SDK, takie jak biblioteki .NET i Java, są często aktualizowane. Inne zestawy SDK lub zestawy SDK dla innych języków mogą być aktualizowane rzadziej.

  • Wiele języków programowania lub struktur. Można użyć wielu technologii do obsługi różnych obciążeń złożonych. Należy jednak unikać rozrastania się, ponieważ wprowadza złożoność zarządzania i wyzwania operacyjne.

  • Opcja obliczeniowa. Starsze lub zastrzeżone oprogramowanie może nie działać w usługach PaaS. Ponadto w kontenerach może nie być możliwe dołączenie starszego lub zastrzeżonego oprogramowania.

Zalecenia dotyczące projektowania

  • Oceń wszystkie odpowiednie zestawy SDK platformy Azure pod kątem potrzebnych możliwości i wybranych języków programowania. Zweryfikuj wyrównanie z wymaganiami niefunkcjonanymi.

  • Zoptymalizuj wybór języków programowania i struktur na poziomie mikrousług. Używaj wielu technologii zgodnie z potrzebami.

  • Określanie priorytetów zestawu .NET SDK w celu zoptymalizowania niezawodności i wydajności. Zestawy SDK platformy Azure platformy .NET zwykle zapewniają więcej możliwości i są często aktualizowane.

Następny krok

Zapoznaj się z zagadnieniami dotyczącymi platformy aplikacji.