Wzorzec kolejki priorytetowej

Określanie priorytetów żądań wysyłanych do usług w taki sposób, aby obciążenie przetwarzało żądania o wysokim priorytcie szybciej niż żądania o niższym priorytcie. Takie podejście używa komunikatów wysyłanych do co najmniej jednej kolejki i jest przydatne w przypadku aplikacji, które zapewniają różne poziomy usług lub umowy dotyczące poziomu usług (SLA) do różnych typów żądań lub klientów.

Kontekst i problem

Obciążenia mogą wymagać zarządzania zadaniami i przetwarzania ich z różnym poziomem ważności i pilności. Niektóre zadania wymagają natychmiastowej uwagi, podczas gdy inne mogą czekać. Niepowodzenie rozwiązywania problemów z zadaniami o wysokim priorytcie może mieć wpływ na środowisko użytkownika i naruszenie umów SLA.

Aby efektywnie obsługiwać zadania na podstawie ich priorytetu, obciążenia muszą odpowiednio przetwarzać i uruchamiać zadania. Domyślnie większość obciążeń przetwarza zadania w kolejności, w której docierają, przy użyciu struktury kolejki pierwszy na wyjeździe (FIFO). Takie podejście nie uwzględnia różnego znaczenia zadania.

Rozwiązanie

Kolejki priorytetowe umożliwiają obciążenia przetwarzania zadań na podstawie ich priorytetu, a nie wyłącznie według ich kolejności przybycia. Aplikacja lub producent , który wysyła żądanie, przypisuje wartość priorytetu do komunikatu, a konsumenci przetwarzają komunikaty według priorytetu. Wzorzec kolejki priorytetu spełnia następujące wymagania:

  • Obsługuje zadania o różnej pilności i ważności: Masz zadania z różnymi poziomami pilności i ważności i musisz upewnić się, że przetwarzasz bardziej krytyczne zadania przed mniej krytycznymi zadaniami.

  • Obsługuje różne umowy SLA: Oferujesz różne umowy SLA dla różnych klientów i musisz zapewnić klientom o wysokim priorytetu lepszą wydajność i dostępność.

  • Uwzględnia różne potrzeby zarządzania obciążeniami: Masz obciążenie, które musi natychmiast zaspokoić niektóre zadania, podczas gdy zadania są mniej pilne, mogą czekać.

Istnieją dwa główne podejścia do implementowania wzorca kolejki priorytetu:

  • Pojedyncza kolejka: Każdy komunikat ma przypisaną wartość priorytetu, a wszystkie komunikaty używają tej samej kolejki.

  • Wiele kolejek: Każdy komunikat ma przypisaną wartość priorytetu, a komunikaty o różnych priorytetach używają oddzielnych kolejek.

Pojedyncza kolejka

W podejściu do jednej kolejki aplikacja przypisuje priorytet do każdego komunikatu i wysyła wszystkie komunikaty do jednej kolejki. Kolejka porządkuje komunikaty według priorytetu, zapewniając, że użytkownicy przetwarzają komunikaty o wyższym priorytcie przed komunikatami o niższym priorytcie.

Diagram ilustrujący mechanizm kolejkowania obsługujący priorytetyzację komunikatów.

Wiele kolejek

Wiele kolejek oddziela komunikaty według priorytetu. Aplikacja przypisuje priorytet do każdego komunikatu i kieruje komunikat do kolejki, która odpowiada jego priorytetowi, w którym konsumenci przetwarzają komunikaty. Rozwiązanie z wieloma kolejkami może używać jednej puli odbiorców lub wielu pul odbiorców.

Pojedyncza pula odbiorców

W ramach konfiguracji pojedynczej puli wszystkie kolejki współdzielą tę samą pulę odbiorców. Konsumenci przetwarzają komunikaty z kolejki o najwyższym priorytcie i przetwarzają komunikaty z kolejek o niższym priorytcie tylko wtedy, gdy nie ma więcej komunikatów o wysokim priorytcie. W związku z tym pojedyncze pule odbiorców zawsze przetwarzają komunikaty o wyższym priorytcie przed niższym priorytetem. Ta konfiguracja może prowadzić do ciągłego opóźnienia komunikatów o niższym priorytcie i potencjalnie nigdy nie są przetwarzane.

Diagram ilustrujący używanie pojedynczej puli odbiorców dla wszystkich priorytetów.

Użyj pojedynczej puli odbiorców z następujących powodów:

  • Proste zarządzanie. Użyj pojedynczej puli odbiorców, gdy łatwa konfiguracja i konserwacja są priorytetem. Pojedyncza pula zmniejsza złożoność konfiguracji i monitorowania.

  • Ujednolicone potrzeby przetwarzania. Użyj pojedynczej puli odbiorców, gdy zadania przychodzące są podobne do typu.

Wiele pul odbiorców

W wielu pulach odbiorców każda kolejka ma dedykowaną pulę odbiorców. Kolejki o wyższym priorytcie używają większej liczby użytkowników lub wyższych warstw wydajności do szybszego przetwarzania komunikatów niż kolejki o niższym priorytcie.

Diagram ilustrujący używanie oddzielnych pul odbiorców dla każdego priorytetu.

Użyj wielu pul odbiorców z następujących powodów:

  • Ścisłe wymagania dotyczące wydajności. Użyj wielu pul odbiorców, gdy różne priorytety zadań mają ścisłe wymagania dotyczące wydajności, które muszą zostać spełnione niezależnie.

  • Wymagania dotyczące wysokiej niezawodności. Używaj wielu pul odbiorców dla aplikacji, gdy izolacja niezawodności i błędów ma krytyczne znaczenie, a problemy w jednej kolejce nie mogą mieć wpływu na inne kolejki.

  • Złożone aplikacje. Używaj wielu pul odbiorców w przypadku złożonych aplikacji, w których różne zadania wymagają różnych właściwości przetwarzania i gwarancji wydajności.

Problemy i zagadnienia

Podczas podejmowania decyzji o zaimplementowaniu tego wzorca należy wziąć pod uwagę następujące kwestie:

Zalecenia ogólne

  • Jasno zdefiniuj priorytety. Ustanów odrębne i jasne poziomy priorytetów, które są istotne dla twojego rozwiązania. Można na przykład zdefiniować komunikaty o wysokim priorytcie jako te, które wymagają przetwarzania w ciągu 10 sekund. Zidentyfikuj wymagania konsumentów dotyczące obsługi elementów o wysokim priorytcie i odpowiednio przydziel niezbędne zasoby.

  • Dynamiczne dostosowywanie pul odbiorców. Skaluj rozmiar pul odbiorców na podstawie długości kolejki, która jest obsługiwana.

  • Monitorowanie kondycji kolejki. Śledź głębokość kolejki, opóźnienie przetwarzania, liczbę dostaw i przepływność, aby można było wykrywać listy prac i spowolnienia przed ich wpływem na pracę.

  • Użyj kolejek utraconych komunikatów. Przenieś zatrute komunikaty do kolejki utraconych komunikatów po konfigurowalnej liczbie prób dostarczenia, dzięki czemu jeden z nieprawidłowych komunikatów nie blokuje ścieżki priorytetu.

  • Określanie priorytetów poziomów usług. Zaimplementuj kolejki priorytetów, aby spełnić potrzeby biznesowe, które wymagają priorytetowej dostępności lub wydajności. Na przykład klienci o wysokim priorytcie mogą otrzymać wyższy poziom usług, aby mieli lepszą wydajność i dostępność.

  • Rozważ przetwarzanie o niskim priorytcie. Zdecyduj, czy wszystkie elementy o wysokim priorytcie muszą być przetwarzane przed wszystkimi elementami o niższym priorytcie. Jeśli to możliwe, dynamicznie zwiększa priorytet starych komunikatów, aby upewnić się, że komunikaty o niskim priorytcie ostatecznie są przetwarzane.

  • Optymalizowanie i minimalizowanie kosztów. Natychmiast przetwarzaj zadania krytyczne dla dostępnych użytkowników. Zaplanuj mniej krytyczne zadania w tle w krótszym czasie pracy.

    Jeśli używasz jednej kolejki, zoptymalizuj koszty, skalując z powrotem liczbę użytkowników. Komunikaty o wysokim priorytcie najpierw przetwarzają się, ale prawdopodobnie wolniej, podczas gdy komunikaty o niższym priorytcie mogą napotykać dłuższe opóźnienia.

  • Ochrona procesorów przed szczytami zapotrzebowania. Jeśli tempo napływu od producenta może przekroczyć zdolność przetwarzania konsumenta, połącz ten wzorzec ze wzorcem wyrównywania obciążenia opartym na kolejce. Takie podejście buforuje wzrost ruchu i pomaga zapobiegać przeciążeniu zasobów przetwarzania podrzędnego.

Zalecenia dotyczące wielu kolejek

  • Monitorowanie szybkości przetwarzania. Aby upewnić się, że komunikaty są przetwarzane według oczekiwanych stawek, stale monitoruj szybkość przetwarzania kolejek o wysokim i niskim priorytcie.

  • Wdrożenie wywłaszczania i zawieszenia. Jeśli używasz wielu kolejek z jedną pulą odbiorców, zaimplementuj algorytm, który zapewnia, że kolejki o wysokim priorytcie są zawsze obsługiwane przed kolejkami o niższym priorytcie.

  • Rozważ koszty kolejki. Należy pamiętać o kosztach finansowych związanych z kolejkami sprawdzania i przetwarzania. Niektóre usługi kolejek pobierają opłaty za publikowanie, pobieranie i wykonywanie zapytań o komunikaty. Te opłaty mogą wzrosnąć wraz z liczbą kolejek.

Kiedy należy używać tego wzorca

Użyj tego wzorca, gdy:

  • Musisz spełnić różne cele opóźnienia lub poziomu usług dla różnych klas pracy, takich jak premium i standardowe żądania klientów.

  • Praca dociera do serii i należy najpierw chronić operacje krytyczne przez przetwarzanie komunikatów o wysokim priorytcie podczas odroczenia pracy o niższym priorytcie.

Ten wzorzec może nie być odpowiedni w następujących przypadkach:

  • Wszystkie elementy robocze mają podobne znaczenie biznesowe, a ścisłe przetwarzanie FIFO jest ważniejsze niż planowanie oparte na priorytetach.

  • Zadania mają silne zależności porządkowania między poziomami priorytetu, a zmiana kolejności pracy według priorytetu może spowodować niespójne wyniki lub wymagać złożonej logiki koordynacji.

Projektowanie obciążenia pracy

Oceń sposób użycia wzorca kolejki priorytetowej w projekcie obciążenia w celu rozwiązania celów i zasad omówionych w filarach platformy Azure Well-Architected Framework. Poniższa tabela zawiera wskazówki dotyczące tego, jak ten wzorzec obsługuje cele poszczególnych filarów.

Filar Jak ten wzorzec obsługuje cele filaru
Decyzje projektowe dotyczące niezawodności pomagają obciążeniu stać się odporne na awarię i zapewnić, że zostanie przywrócony do w pełni funkcjonalnego stanu po wystąpieniu awarii. Oddzielenie elementów na podstawie priorytetu biznesowego umożliwia skoncentrowanie wysiłków związanych z niezawodnością na najbardziej krytycznej pracy.

- RE:02 Przepływy krytyczne
Efektywność wydajności pomaga wydajnie sprostać wymaganiom dzięki optymalizacjom skalowania, danych i kodu. Oddzielenie elementów na podstawie priorytetu biznesowego umożliwia skoncentrowanie wysiłków związanych z wydajnością w najbardziej czasochłonnej pracy.

- PE:09 Przepływy krytyczne

Jeśli ten wzorzec wprowadza kompromisy w ramach filaru, rozważ je przed celami innych filarów.

Example

Przykładowy wzorzec kolejki priorytetu w GitHub pokazuje implementację wzorca kolejki priorytetów, który używa Azure Service Bus tematów i subskrypcji. W tym przykładzie wdrażane jest bezpieczne konto magazynu, zasób usługi Application Insights na potrzeby monitorowania oraz przestrzeń nazw Service Bus umożliwiająca komunikację między funkcjami nadawcy i użytkownika.

Wdrożenie obejmuje trzy aplikacje funkcji: jeden nadawca i dwóch użytkowników. Aplikacje konsumenckie używają różnych maksymalnych liczb wystąpień do symulowania priorytetyzacji komunikatów. Funkcja funcPriorityQueueConsumerHigh może skalować w poziomie do 200 wystąpień, a funcPriorityQueueConsumerLow funkcja jest ograniczona do 40 wystąpień. Wszystkie aplikacje funkcji korzystają z planu Flex Consumption i są połączone z usługą Application Insights na potrzeby diagnostyki i monitorowania.

Przypisania ról zapewniają bezpieczny dostęp do Service Bus i magazynu przy użyciu tożsamości zarządzanych. Wszystkie aplikacje funkcji współdzielą to samo konto magazynu i zasób usługi Application Insights. Ta konfiguracja umożliwia scentralizowanie obserwowania i rejestrowania.

Na poniższym diagramie przedstawiono architekturę kolejki priorytetów:

Diagram przedstawiający sposób implementowania kolejki priorytetów przy użyciu Service Bus.

Na powyższym diagramie:

  1. Aplikacja (producent). Aplikacja PriorityQueueSender tworzy komunikaty, przypisuje niestandardową właściwość aplikacji wywoływaną Priority do każdego komunikatu Priority i ustawia wartość na High lub Low.

  2. Broker komunikatów i temat. Broker komunikatów Service Bus wysyła komunikaty do pojedynczego tematu Service Bus o nazwie messages. Service Bus używa filtrów SQL do kierowania każdego komunikatu do subskrypcji o wysokim priorytecie lub niskim priorytecie na podstawie jego Priority wartości.

  3. Wiele pul odbiorców. Pule PriorityQueueConsumerHigh odbiorców i PriorityQueueConsumerLow odpowiadają na komunikaty z subskrypcji o wysokim priorytcie lub niskim priorytcie przy użyciu wyzwalaczy Azure Functions Service Bus.

Rola w przykładzie usługa Azure w przykładzie Nazwa w przykładzie
Aplikacja (producent) aplikacja Azure Functions PriorityQueueSender
Broker komunikatów Azure Service Bus <przestrzeń nazw usługi Service Bus>
Temat komunikatu Temat usługi Azure Service Bus messages
Subskrypcje komunikatów subskrypcje Azure Service Bus highPriority
lowPriority
Klienci aplikacja Azure Functions KolejkaPriorytetowaKonsumentWysoki
PriorityQueueConsumerLow

Następne kroki

Podczas implementowania tego wzorca mogą być przydatne następujące wzorce:

  • Queue-Based wzorzec bilansowania obciążenia: użyj kolejki jako buforu między pobieraniem żądań i przetwarzaniem. Użyj go ze wzorcem kolejki priorytetu, gdy potrzebujesz ochrony przed wzrostem i zróżnicowanej obsługi.

  • Wzorzec konkurujących odbiorców: zaimplementuj wielu użytkowników, którzy nasłuchują tej samej kolejki i przetwarzają zadania równolegle w celu zwiększenia przepływności. Tylko jeden użytkownik przetwarza każdy komunikat.

  • Wzorzec ograniczania przepustowości: zaimplementuj ograniczanie przepustowości przy użyciu kolejek do zarządzania szybkościami żądań. Użyj komunikatów priorytetowych, aby określić priorytety żądań od krytycznych aplikacji lub klientów o wysokiej wartości w porównaniu z mniej ważnymi.