Wzorzec choreografii

Pozwól każdej usłudze decydować, kiedy i jak przetwarzać operację biznesową, zamiast polegać na centralnym orkiestratorze. Takie podejście decentralizuje logikę przepływu pracy i dystrybuuje obowiązki między składniki systemu.

Kontekst i problem

Zazwyczaj aplikacja oparta na chmurze jest podzielona na kilka małych usług, które współpracują ze sobą w celu przetworzenia kompleksowej transakcji biznesowej. Pojedyncza operacja w ramach transakcji może spowodować wiele połączeń punkt-do-punktu pomiędzy wszystkimi usługami. W idealnym przypadku te usługi są luźno powiązane. Projektowanie rozproszonego, wydajnego i skalowalnego przepływu pracy jest trudne, ponieważ obejmuje złożoną komunikację międzyusługową.

Typowym wzorcem komunikacji jest użycie scentralizowanej usługi lub orkiestratora. Żądania przychodzące przepływają przez koordynatora, gdy deleguje operacje do odpowiednich usług. Każda usługa wykonuje swoją odpowiedzialność i nie jest świadoma ogólnego przepływu pracy.

Diagram przepływu pracy, który używa centralnego koordynatora do przetwarzania żądań.

Wzorzec orkiestratora zazwyczaj implementuje się jako oprogramowanie dostosowane do potrzeb, które ma wiedzę na temat ról i obowiązków usług w systemie. Jedną z zalet tego podejścia jest to, że orkiestrator może skonsolidować stan transakcji na podstawie wyników poszczególnych operacji wykonywanych przez usługi podrzędne.

Takie podejście stwarza również pewne przeszkody. Dodawanie lub usuwanie usług może spowodować przerwanie istniejącej logiki, ponieważ konieczne jest ponowne połączenie części ścieżki komunikacyjnej. Ta zależność sprawia, że implementacja orkiestratora jest złożona i trudna do utrzymania. Orkiestrator może negatywnie wpłynąć na niezawodność obciążenia. Obciążenie może powodować wąskie gardła wydajności i być pojedynczym punktem awarii (SPoF). Gdy orkiestrator ulegnie awarii lub stanie się przeciążony, awaria może być propagowana do wszystkich zależnych usług podrzędnych.

Rozwiązanie

Deleguj logikę obsługi transakcji między usługami. Pozwól każdej usłudze uczestniczyć w procesie komunikacyjnym w operacji biznesowej i decydować, kiedy oraz jak przetwarzać ten proces.

Wzorzec choreografii minimalizuje zależność od niestandardowego oprogramowania, które centralizuje przepływ pracy komunikacji. Składniki implementują wspólną logikę, ponieważ choreografują przepływ pracy między sobą bez bezpośredniej komunikacji ze sobą.

Typowym sposobem implementacji choreografii jest użycie brokera komunikatów, który buforuje żądania do momentu, gdy komponenty podrzędne przyjmują je i przetwarzają. Na poniższej ilustracji przedstawiono obsługę żądań za pomocą modelu wydawcy-subskrybenta.

Diagram przedstawiający sposób przetwarzania żądania przez brokera komunikatów.

  1. Żądania klienta są umieszczane w kolejce jako komunikaty w brokerze wiadomości.

  2. Usługi lub subskrybent sprawdza u brokera, czy na podstawie wdrożonej logiki biznesowej może przetworzyć komunikat. Broker może również wypychać komunikaty do subskrybentów zainteresowanych tą wiadomością.

  3. Każda subskrybowana usługa wykonuje swoją operację zgodnie z instrukcją zawartą w komunikacie i odpowiada brokerowi komunikatem o powodzeniu lub niepowodzeniu operacji.

  4. Jeśli operacja zakończy się pomyślnie, usługa może opublikować komunikat w tej samej kolejce lub w innej kolejce komunikatów, aby inna usługa mogła w razie potrzeby kontynuować przepływ pracy. Jeśli operacja zakończy się niepowodzeniem, usługa publikuje komunikat o błędzie. Usługi subskrybujące ten komunikat mogą uruchamiać wstępnie zdefiniowane akcje kompensacyjne dla nieudanej operacji lub całej transakcji.

Problemy i zagadnienia

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

Kiedy należy używać tego wzorca

Użyj tego wzorca, gdy:

  • Komponenty podrzędne obsługują operacje atomowe niezależnie od siebie w modelu fire and forget. Każdy komponent wykonuje zadanie, a następnie sygnalizuje innym komponentom jego ukończenie za pośrednictwem brokera komunikatów. Usługa inicjująca nie zarządza ani nie śledzi zadania po jego wysłaniu, ale usługi podrzędne nadal komunikują wyniki za pośrednictwem zdarzeń.

  • Oczekujesz, że składniki będą często aktualizowane i zastępowane. Ten wzorzec umożliwia modyfikowanie aplikacji z mniejszym nakładem pracy i minimalnymi zakłóceniami w istniejących usługach.

  • Architektury bezserwerowe są używane do prostych przepływów pracy. Składniki mogą być krótkoczasowe i sterowane zdarzeniami. Gdy wystąpi zdarzenie, usługa tworzy składniki, które wykonują zadanie, a usługa usuwa składniki po zakończeniu tego zadania.

  • Komunikacja między powiązanymi kontekstami wymaga luźnego sprzężenia między granicami domeny. W przypadku komunikacji wewnątrz jednego ograniczonego kontekstu rozważ zamiast tego wzorzec orkiestratora, w zależności od złożoności i preferencji zespołu.

  • Centralny koordynator wprowadza wąskie gardło wydajności.

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

  • Aplikacja jest złożona i wymaga centralnego składnika do obsługi logiki udostępnionej, aby zachować lekkie składniki podrzędne.

  • Komunikacja punkt-punkt między składnikami jest nieunikniona.

  • Aby skonsolidować wszystkie operacje obsługiwane przez składniki podrzędne, należy użyć logiki biznesowej.

Projektowanie obciążeń roboczych

Oceń, jak używać wzorca choreografii w projektowaniu obciążenia, odpowiadając na cele i zasady opisane 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
Doskonałość operacyjna pomaga zapewnić jakość obciążeń dzięki ustandaryzowanym procesom i spójności zespołu. Składniki rozproszone w tym wzorcu są autonomiczne i zaprojektowane tak, aby można je było zastąpić, dzięki czemu można modyfikować obciążenie przy użyciu mniej ogólnej zmiany w systemie.

- OE:04 Narzędzia i procesy
Efektywność wydajności pomaga wydajnie sprostać wymaganiom dzięki optymalizacjom skalowania, danych i kodu. Ten wzorzec oferuje alternatywę, gdy w scentralizowanej topologii orkiestracji występują wąskie gardła wydajności.

- PE:02 Planowanie pojemności
- PE:05 Skalowanie i partycjonowanie

Podobnie jak w przypadku każdej decyzji projektowej, należy rozważyć wszelkie kompromisy w stosunku do celów innych filarów, które mogą zostać wprowadzone przy użyciu tego wzorca.

Przykład

W tym przykładzie pokazano wzorzec choreografii przez utworzenie obciążenia natywnego dla chmury opartego na zdarzeniach, które uruchamia funkcje wraz z mikrousługami. Gdy klient żąda wysłania przesyłki, system przypisuje drona. Gdy pakiet będzie gotowy do odbioru przez zaplanowanego drona, rozpocznie się proces dostawy. Podczas gdy pakiet jest w transporcie, proces obsługuje dostawę do momentu otrzymania statusu wysłany. Aby uzyskać pełną architekturę referencyjną, zobacz Mikrousługi z Azure Container Apps.

Diagram modelu obciążenia natywnego dla chmury sterowanego zdarzeniami, który implementuje wzorzec choreografii.

Usługa pobierania odbiera żądania klientów i konwertuje je na komunikaty zawierające szczegóły dotyczące dostawy. Transakcje biznesowe rozpoczynają się po przetworzeniu tych nowych komunikatów przez usługi.

Jedna transakcja biznesowa klienta wymaga trzech odrębnych operacji biznesowych:

  • Tworzenie lub aktualizowanie pakietu.

  • Przeznacz drona do dostarczenia przesyłki.

  • Obsługa dostarczania, w tym sprawdzanie i wysyłanie powiadomienia, gdy pakiet jest dostarczany.

Mikrousługa paczek, harmonogramowanie dronów i mikrousługi dostarczania wykonują procesy biznesowe. Usługi używają komunikatów zamiast centralnego koordynatora do komunikowania się ze sobą. Każda usługa musi z wyprzedzeniem zaimplementować protokół, który koordynuje przepływ pracy biznesowego w sposób zdecentralizowany.

Projektowanie

Usługi przetwarzają transakcje biznesowe w sekwencji za pośrednictwem wielu etapów. Każdy przeskok udostępnia jedną magistralę komunikatów wśród wszystkich usług biznesowych.

Gdy klient wysyła żądanie dostarczenia za pośrednictwem punktu końcowego HTTP, usługa pozyskiwania odbiera je, konwertuje je na komunikat, a następnie publikuje komunikat do udostępnionej magistrali komunikatów. Subskrybowane usługi biznesowe korzystają z nowych komunikatów dodawanych do magistrali. Gdy usługa biznesowa odbierze komunikat, zakończy operację pomyślnie lub żądanie zakończy się niepowodzeniem lub upłynął limit czasu. Jeśli żądanie zakończy się powodzeniem, usługa odpowiada na magistralę z Ok kodem stanu, zgłasza nowy komunikat operacji i wysyła go do magistrali komunikatów. Jeśli żądanie zakończy się niepowodzeniem lub przekroczy limit czasu, usługa przekaże kod przyczyny błędu do magistrali komunikatów i przeniesie wiadomość do kolejki wiadomości niedostarczonych za pośrednictwem Azure Service Bus. Usługa również nieaktywne wiadomości, których nie może odbierać ani przetwarzać w określonym czasie.

Ten projekt używa wielu magistrali komunikatów do przetwarzania całej transakcji biznesowej. Usługi Azure Service Bus i Azure Event Grid udostępniają platformę usługi obsługi komunikatów dla tego projektu. Obciążenie robocze działa w Azure Container Apps. Usługa pozyskiwania działa jako funkcja Azure hostowana w usłudze Container Apps, podczas gdy pakiet, harmonogram dronów i usługi dostarczania działają jako mikrousługi w tym samym środowisku usługi Container Apps. Usługa Container Apps obsługuje przetwarzanie sterowane zdarzeniami , które uruchamia logikę biznesową.

Ten projekt zapewnia również, że choreografia odbywa się w sekwencji. Pojedyncza przestrzeń nazw usługi Service Bus zawiera temat zawierający dwie subskrypcje i kolejkę z obsługą sesji. Usługa pozyskiwania publikuje komunikaty w temacie. Usługa pakietu i usługa harmonogramowania dronów subskrybują tematy i publikują komunikaty, które powiadamiają kolejkę o pomyślnych żądaniach. Dołącz wspólny identyfikator sesji, który kojarzy identyfikator GUID z identyfikatorem dostarczania, aby usługa dostarczania mogła skorelować dwa komunikaty potrzebne dla każdej transakcji. Jedna wiadomość potwierdza, że pakiet jest gotowy, a drugi potwierdza zaplanowanie drona. Bez tej korelacji opartej na sesji usługa dostarczająca nie ma możliwości powiązania związanych ze sobą komunikatów na kolejnych niezależnych etapach przesyłania, ponieważ żaden centralny koordynator nie śledzi stanu transakcji. Usługa dostarczania czeka na dwa powiązane komunikaty dla każdej transakcji. Pierwszy komunikat wskazuje, że przesyłka jest gotowa do wysyłki, a drugi komunikat sygnalizuje, że zaplanowano wysłanie drona.

W tym projekcie usługa Service Bus obsługuje komunikaty o wysokiej wartości, które nie mogą zostać utracone ani zduplikowane podczas całego procesu dostarczania. Po wysłaniu przesyłki, zmiana stanu jest publikowana do usługi Event Grid. Nadawca zdarzeń nie ma oczekiwań co do sposobu obsługi zmiany stanu. Podrzędne usługi organizacji, których ten projekt nie obejmuje, mogą nasłuchiwać tego typu zdarzenia i uruchamiać określoną logikę biznesową, taką jak wysyłanie wiadomości e-mail o stanie zamówienia do użytkownika.

Jeśli wdrażasz ten wzorzec w innej usłudze obliczeniowej, takiej jak AKS, możesz wdrożyć ambassador jako sidecar w tym samym podzie co aplikacja biznesowa. Kolokacja minimalizuje opóźnienie komunikacji, ale serwer proxy dodaje obciążenie przetwarzania i zasobów oraz skaluje je wraz z aplikacją. Użyj tego podejścia, gdy potrzebujesz niezależnych od języka kwestii związanych z łącznością, których platforma nie zapewnia.

Aby uniknąć kaskadowych operacji ponawiania, które mogą prowadzić do wielu prób, usługi biznesowe powinny natychmiast oznaczać niedopuszczalne komunikaty. Wzbogacanie tych komunikatów przy użyciu typowych kodów przyczyn lub zdefiniowanego kodu aplikacji, aby usługi mogły przenieść je do biblioteki DLQ. Rozważ zaimplementowanie wzorca saga w celu zarządzania problemami spójności z usług podrzędnych. Na przykład inna usługa obsługuje wiadomości martwe na potrzeby naprawy tylko przez uruchomienie rekompensaty, ponownych prób lub transakcji przestawnej.

Usługi biznesowe są idempotentne, aby upewnić się, że operacje ponawiania nie tworzą zduplikowanych zasobów. Na przykład usługa pakietowa wykorzystuje operacje upsert do dodawania danych do magazynu danych.

Następny krok

Weź pod uwagę te wzorce w projekcie choreografii: