Architektura sterowana zdarzeniami składa się z producentów zdarzeń, którzy generują strumień zdarzeń, odbiorców zdarzeń, którzy nasłuchują tych zdarzeń, oraz kanałów zdarzeń, które przesyłają zdarzenia od producentów do konsumentów.
Zdarzenia są dostarczane prawie w czasie rzeczywistym, więc odbiorcy mogą natychmiast na nie reagować w momencie ich wystąpienia. Producenci są oddzieleni od konsumentów — producent nie wie, którzy konsumenci słuchają. Odbiorcy są również całkowicie niezależni od siebie nawzajem, a każdy odbiorca widzi wszystkie zdarzenia. To podejście różni się od wzorca konkurujących odbiorców, w którym odbiorcy ściągają komunikaty z kolejki, a komunikat jest przetwarzany tylko raz (zakładając brak błędów). W niektórych systemach, takich jak IoT, zdarzenia muszą być pozyskiwane w bardzo dużych ilościach.
Architektura sterowana zdarzeniami może używać modelu publikowania/subskrybowania (nazywanego również pub/sub) lub modelu strumienia zdarzeń.
Publikowanie/subskrybowanie: infrastruktura obsługi komunikatów śledzi subskrypcje. Gdy zostaje opublikowane zdarzenie, wysyła zdarzenie do wszystkich subskrybentów. Po odebraniu zdarzenia nie można go odtworzyć, a nowi subskrybenci nie widzą zdarzenia.
Przesyłanie strumieniowe zdarzeń: zdarzenia są zapisywane w dzienniku. Zdarzenia są ściśle uporządkowane (w ramach partycji) i trwałe. Klienci nie subskrybują strumienia; zamiast tego klient może odczytywać dane z dowolnej części strumienia. Klient jest odpowiedzialny za przesuwanie pozycji w strumieniu. Oznacza to, że klient może dołączyć w dowolnym momencie i może odtwarzać ponownie zdarzenia.
Po stronie odbiorcy znajduje się parę typowych odmian:
Proste przetwarzanie zdarzeń. Zdarzenie natychmiast wyzwala akcję odbiorcy. Na przykład można użyć usługi Azure Functions z wyzwalaczem usługi Service Bus, tak aby funkcja była wykonywana zawsze, gdy komunikat jest publikowany do tematu usługi Service Bus.
Podstawowa korelacja zdarzeń. Użytkownik musi przetworzyć niewielką liczbę odrębnych zdarzeń biznesowych, zwykle skorelowanych przez jakiś identyfikator, utrwalając niektóre informacje z wcześniejszych zdarzeń do użycia podczas przetwarzania późniejszych zdarzeń. Ten wzorzec jest obsługiwany przez biblioteki, takie jak NServiceBus i MassTransit.
Złożone przetwarzanie zdarzeń. Użytkownik przetwarza serię zdarzeń, wyszukując wzorce w danych zdarzeń przy użyciu technologii takiej jak usługa Azure Stream Analytics. Na przykład można agregować odczyty z urządzenia osadzonego na przestrzeni przedziału czasu i wygenerować powiadomienie, jeśli średnia ruchoma przekroczy pewien próg.
Przetwarzanie strumienia zdarzeń. Platformy do strumieniowego przesyłania danych, takie jak Azure IoT Hub lub Apache Kafka, mogą służyć jako potok w celu pozyskania zdarzeń i przekazania ich do procesorów strumieni. Procesory strumieni przetwarzają lub przekształcają strumień. Dla różnych podsystemów aplikacji może istnieć wiele procesorów strumieni. Ta metoda jest odpowiednia dla obciążeń IoT.
Źródło zdarzenia może być zewnętrzne względem systemu, na przykład fizyczne urządzenia w rozwiązaniu IoT. W takim przypadku system musi mieć możliwość pozyskiwania danych w ilości i przepływności wymaganej przez źródło danych.
Istnieją dwa podstawowe podejścia do struktury ładunków zdarzeń. Jeśli masz kontrolę nad użytkownikami zdarzeń, należy podjąć tę decyzję o strukturze ładunku dla użytkownika; mieszanie podejść zgodnie z potrzebami w ramach pojedynczego obciążenia.
Uwzględnianie wszystkich wymaganych atrybutów w ładunku: to podejście jest używane, gdy użytkownicy mają mieć wszystkie dostępne informacje bez konieczności wykonywania zapytań względem zewnętrznego źródła danych. Może to jednak prowadzić do problemów ze spójnością danych ze względu na wiele systemów rekordów, szczególnie po aktualizacjach. Zarządzanie umowami i przechowywanie wersji mogą również stać się złożone.
Uwzględnianie tylko kluczy w ładunku: w tym podejściu konsumenci pobierają niezbędne atrybuty, takie jak klucz podstawowy, aby niezależnie pobierać pozostałe dane ze źródła danych. Chociaż ta metoda zapewnia lepszą spójność danych ze względu na pojedynczy system rekordów, może działać źle niż pierwsze podejście, ponieważ konsumenci muszą często wykonywać zapytania dotyczące źródła danych. Istnieje mniej problemów dotyczących sprzęgania, przepustowości, zarządzania kontraktami lub przechowywania wersji, ponieważ zdarzenia są mniejsze i prostsze.
Na powyższym diagramie logicznym każdy typ odbiorcy jest przedstawiony jako pojedyncze pole. W praktyce częste jest posiadanie wielu wystąpień odbiorcy, aby uniknąć sytuacji, w której odbiorca stałby się pojedynczym punktem awarii w systemie. Wiele wystąpień może być również niezbędnych, aby obsłużyć liczbę i częstotliwość zdarzeń. Ponadto pojedynczy odbiorca może przetwarzać zdarzenia w wielu wątkach. Może to stanowić wyzwanie, jeśli zdarzenia muszą być przetwarzane w kolejności lub wymagają dokładnie raz semantyki. Zobacz temat Minimize Coordination (Minimalizowanie koordynacji).
Istnieją dwie główne topologie w wielu architekturach opartych na zdarzeniach:
Topologia brokera. Składniki emitują wystąpienia jako zdarzenia do całego systemu, a inne składniki działają na zdarzeniu lub po prostu ignorują zdarzenie. Ta topologia jest przydatna, gdy przepływ przetwarzania zdarzeń jest stosunkowo prosty. Nie ma centralnej koordynacji ani aranżacji, więc ta topologia może być bardzo dynamiczna. Ta topologia jest wysoce oddzielona, co pomaga zapewnić skalowalność, czas odpowiedzi i odporność na uszkodzenia składników. Żaden składnik nie jest właścicielem ani nie zna stanu każdej wieloetapowej transakcji biznesowej, a akcje są wykonywane asynchronicznie. Następnie transakcje rozproszone są ryzykowne, ponieważ nie ma natywnych środków do ponownego uruchomienia lub odtworzenia. Należy dokładnie rozważyć strategie obsługi błędów i interwencji ręcznej, ponieważ ta topologia może być źródłem niespójności danych.
Topologia mediatora. Ta topologia dotyczy niektórych niedociągnięć topologii brokera. Istnieje mediator wydarzenia, który zarządza i kontroluje przepływ wydarzeń. Mediator zdarzeń utrzymuje stan i zarządza możliwościami obsługi błędów i ponownego uruchamiania. W przeciwieństwie do topologii brokera składniki emitować wystąpienia jako polecenia i tylko do wyznaczonych kanałów, zwykle kolejki komunikatów. Te polecenia nie powinny być ignorowane przez użytkowników. Ta topologia oferuje większą kontrolę, lepszą obsługę błędów rozproszonych i potencjalnie lepszą spójność danych. Ta topologia wprowadza zwiększone sprzężenie między składnikami, a mediator zdarzeń może stać się wąskim gardłem lub problemem dotyczącym niezawodności.
Kiedy stosować tę architekturę
- Wiele podsystemów musi przetwarzać te same zdarzenia.
- Przetwarzanie w czasie rzeczywistym z minimalnym opóźnieniem czasowym.
- Złożone przetwarzanie zdarzeń, takie jak dopasowanie wzorca lub agregacja na przestrzeni przedziału czasu.
- Duża ilość i duża szybkość pracy danych, na przykład IoT.
Świadczenia
- Producenci i odbiorcy są całkowicie niezależni.
- Brak integracji punkt-punkt. Łatwo dodawać nowych odbiorców do systemu.
- Odbiorcy mogą reagować na zdarzenia natychmiast, w momencie ich odebrania.
- Wysoce skalowalne, elastyczne i rozproszone.
- Podsystemy mają niezależne widoki strumienia zdarzeń.
Wyzwania
Gwarancja dostarczenia.
W niektórych systemach, szczególnie w scenariuszach IoT, jest niezwykle istotne, aby zagwarantować dostarczenie zdarzeń.
Przetwarzanie zdarzeń w kolejności lub dokładnie jednokrotnie.
Każdy typ odbiorcy zwykle działa w wielu wystąpieniach w celu zapewnienia elastyczności i skalowalności. Może to stanowić wyzwanie, jeśli zdarzenia muszą być przetwarzane w kolejności (w ramach typu odbiorcy) lub logika przetwarzania komunikatów idempotentnych nie jest zaimplementowana.
Koordynowanie komunikatów między usługami.
Procesy biznesowe często obejmują publikowanie wielu usług i subskrybowanie komunikatów w celu osiągnięcia spójnego wyniku w całym obciążeniu. Wzorce przepływu pracy, takie jak wzorzec choreografii i orkiestracja Saga, mogą służyć do niezawodnego zarządzania przepływami komunikatów w różnych usługach.
Obsługa błędów.
Architektura sterowana zdarzeniami używa głównie komunikacji asynchronicznej. Wyzwanie związane z asynchroniczną komunikacją polega na obsłudze błędów. Jednym ze sposobów rozwiązania tego problemu jest użycie oddzielnego procesora obsługi błędów. Dlatego gdy użytkownik zdarzenia napotyka błąd, natychmiast i asynchronicznie wysyła błędne zdarzenie do procesora obsługi błędów i przechodzi dalej. Procesor obsługi błędów próbuje naprawić błąd i wysyła zdarzenie z powrotem do oryginalnego kanału pozyskiwania. Jeśli jednak procesor obsługi błędów ulegnie awarii, może wysłać błędne zdarzenie do administratora w celu dalszej inspekcji. Jeśli używasz procesora obsługi błędów, błędne zdarzenia zostaną przetworzone poza sekwencję po ich ponownym wysłaniu.
Utrata danych.
Innym wyzwaniem z asynchroniczną komunikacją jest utrata danych. Jeśli którykolwiek ze składników ulegnie awarii przed pomyślnym przetworzeniem i przekazaniem zdarzenia do następnego składnika, zdarzenie zostanie porzucone i nigdy nie przejdzie do końcowego miejsca docelowego. Aby zminimalizować ryzyko utraty danych, utrwal zdarzenia podczas przesyłania i usuń lub usuń zdarzenia w kolejce tylko wtedy, gdy następny składnik potwierdził otrzymanie zdarzenia. Te funkcje są zwykle znane jako tryb potwierdzenia klienta i ostatnia obsługa uczestnika.
Implementowanie tradycyjnego wzorca odpowiedzi na żądanie.
Czasami producent zdarzeń wymaga natychmiastowej odpowiedzi od odbiorcy zdarzeń, takiego jak uzyskanie uprawnień klienta przed kontynuowaniem zamówienia. W architekturze sterowanej zdarzeniami komunikacja synchroniczna można osiągnąć za pośrednictwem komunikatów żądań odpowiedzi.
Ten wzorzec jest zwykle implementowany przez użycie wielu kolejek — kolejki żądań i kolejki odpowiedzi. Producent zdarzeń wysyła żądanie asynchroniczne do kolejki żądań, wstrzymuje inną operację w tym zadaniu i oczekuje na odpowiedź w kolejce odpowiedzi; skuteczne przekształcenie tego w proces synchroniczny. Następnie odbiorcy zdarzeń przetwarzają żądanie i wysyłają odpowiedź z powrotem za pośrednictwem kolejki odpowiedzi. Takie podejście zwykle korzysta z identyfikatora sesji do śledzenia, więc producent zdarzeń wie, który komunikat w kolejce odpowiedzi jest powiązany z określonym żądaniem. Oryginalne żądanie może również określić nazwę kolejki odpowiedzi, potencjalnie efemeryczne, w nagłówku odpowiedzi lub inny wzajemnie uzgodniony atrybut niestandardowy.
Utrzymywanie odpowiedniej liczby zdarzeń.
Generowanie nadmiernej liczby drobnych zdarzeń może saturacji i przeciążenia systemu, co utrudnia efektywne analizowanie ogólnego przepływu zdarzeń. Ten problem jest zaostrzony, gdy zmiany muszą zostać wycofane. Z drugiej strony zbyt skonsolidowanie zdarzeń może również powodować problemy, co powoduje niepotrzebne przetwarzanie i odpowiedzi od użytkowników zdarzeń.
Aby osiągnąć właściwą równowagę, należy wziąć pod uwagę konsekwencje zdarzeń i to, czy konsumenci muszą sprawdzić ładunki zdarzeń, aby określić ich odpowiedzi. Na przykład jeśli masz składnik sprawdzania zgodności, może być wystarczająca do opublikowania tylko dwóch typów zdarzeń: zgodnych i niezgodnych. Takie podejście umożliwia przetwarzanie każdego zdarzenia tylko przez odpowiednich odbiorców, uniemożliwiając niepotrzebne przetwarzanie.
Uwagi dodatkowe
- Ilość danych, które należy uwzględnić w zdarzeniu, może być istotnym czynnikiem wpływającym zarówno na wydajność, jak i koszt. Umieszczenie wszystkich istotnych informacji potrzebnych do przetworzenia w samym zdarzeniu może uprościć przetwarzanie kodu i zapisać dodatkowe wyszukiwania. Umieszczenie minimalnej ilości informacji w zdarzeniu, podobnie jak tylko kilka identyfikatorów, skróci czas transportu i koszt, ale wymaga, aby kod przetwarzania wyszukał dodatkowe potrzebne informacje. Aby uzyskać więcej informacji na ten temat, zapoznaj się z tym wpisem w blogu.
- Chociaż żądanie jest widoczne tylko dla składnika obsługi żądań, zdarzenia są często widoczne dla wielu składników w obciążeniu, nawet jeśli te składniki nie lub nie są przeznaczone do ich użycia. Działanie z myślą o "założeniu naruszenia" należy pamiętać o informacjach uwzględnionych w zdarzeniach, aby zapobiec niezamierzonej ekspozycji na informacje.
- Wiele aplikacji używa architektury sterowanej zdarzeniami jako podstawowej architektury; jednak takie podejście może być łączone z innymi stylami architektury, co skutkuje architekturami hybrydowymi. Typowe kombinacje obejmują mikrousługi i potoki i filtry. Integracja architektury sterowanej zdarzeniami zwiększa wydajność systemu, eliminując wąskie gardła i zapewniając ciśnienie wsteczne podczas dużych ilości żądań.
- Określone domeny często obejmują wielu producentów zdarzeń, odbiorców lub kanałów zdarzeń. Zmiany w określonej domenie mogą mieć wpływ na wiele składników.
Powiązane zasoby
- Wideo dyskusyjne społeczności dotyczące zagadnień dotyczących wyboru między choreografią a orkiestracją.