Architektura sterowana zdarzeniami
Architektura sterowana zdarzeniami ( EDA ) to paradygmat architektury oprogramowania promujący wytwarzanie, wykrywanie, wykorzystywanie i reagowanie na zdarzenia .
Przegląd
Zdarzenie można zdefiniować jako „istotną zmianę stanu ”. Na przykład, gdy konsument kupuje samochód, stan samochodu zmienia się z „na sprzedaż” na „sprzedany”. Architektura systemu dealera samochodowego może traktować tę zmianę stanu jako zdarzenie, którego wystąpienie może być znane innym aplikacjom w architekturze. Z formalnego punktu widzenia to, co jest produkowane, publikowane, propagowane, wykrywane lub konsumowane, to (zwykle asynchroniczny) komunikat zwany powiadomieniem o zdarzeniu, a nie samo zdarzenie, czyli zmiana stanu, która wywołała emisję komunikatu. Wydarzenia nie podróżują, po prostu się wydarzają. Jednak termin zdarzenie jest często używany metonimicznie do określenia samego powiadomienia, co może prowadzić do pewnych nieporozumień. Wynika to z faktu, że architektury sterowane zdarzeniami są często projektowane na architekturach sterowanych komunikatami , w których taki wzorzec komunikacji wymaga, aby jedno z danych wejściowych było tylko tekstem, komunikatem, aby rozróżnić sposób obsługi każdej komunikacji.
Ten wzorzec architektoniczny może być zastosowany przy projektowaniu i wdrażaniu aplikacji i systemów, które przekazują zdarzenia pomiędzy luźno powiązanymi komponentami oprogramowania i usługami . System sterowany zdarzeniami zazwyczaj składa się z emiterów zdarzeń (lub agentów), konsumentów zdarzeń (lub ujścia) i kanałów zdarzeń. Emitery są odpowiedzialne za wykrywanie, gromadzenie i przesyłanie zdarzeń. Emiter zdarzeń nie zna konsumentów zdarzenia, nie wie nawet, czy konsument istnieje, a jeśli istnieje, nie wie, w jaki sposób zdarzenie jest wykorzystywane lub dalej przetwarzane. Umywalki mają obowiązek zastosować reakcję, gdy tylko zostanie zaprezentowane zdarzenie. Reakcja może, ale nie musi, być całkowicie zapewniona przez sam zlew. Na przykład ujście może po prostu odpowiadać za filtrowanie, przekształcanie i przekazywanie zdarzenia do innego komponentu lub może zapewniać samodzielną reakcję na takie zdarzenie. Kanały zdarzeń to kanały, w których zdarzenia są przesyłane od emiterów zdarzeń do odbiorców zdarzeń. Wiedza o prawidłowym rozkładzie zdarzeń jest obecna wyłącznie w kanale zdarzeń. [ Potrzebne źródło ] Fizyczna implementacja kanałów zdarzeń może opierać się na tradycyjnych komponentach, takich jak zorientowane na komunikaty oprogramowanie pośrednie lub komunikacja punkt-punkt, co może wymagać bardziej odpowiednich transakcyjnych ram wykonawczych [ wyjaśnij ] .
Budowanie systemów opartych na architekturze sterowanej zdarzeniami upraszcza poziomą skalowalność modeli przetwarzania rozproszonego i zwiększa ich odporność na awarie. Dzieje się tak, ponieważ stan aplikacji można kopiować w wielu równoległych migawkach w celu zapewnienia wysokiej dostępności. Nowe zdarzenia mogą być inicjowane w dowolnym miejscu, ale co ważniejsze, rozprzestrzeniają się w sieci magazynów danych, aktualizując każdy z nich w miarę ich nadejścia. Dodawanie dodatkowych węzłów również staje się trywialne: możesz po prostu skopiować stan aplikacji, przesłać do niej strumień zdarzeń i uruchomić z nią.
Architektura sterowana zdarzeniami może uzupełniać architekturę zorientowaną na usługi (SOA), ponieważ usługi mogą być aktywowane przez wyzwalacze wyzwalane w przypadku nadchodzących zdarzeń. Ten paradygmat jest szczególnie przydatny, gdy zlew nie zapewnia samowystarczalnego wykonawczego [ wyjaśnij ] .
SOA 2.0 ewoluuje implikacje zapewniane przez architektury SOA i EDA na bogatszy, bardziej niezawodny poziom, wykorzystując nieznane wcześniej związki przyczynowe w celu utworzenia nowego wzorca zdarzeń. [ niejasne ] Ten nowy wzorzec analizy biznesowej uruchamia dalsze autonomiczne przetwarzanie wykonywane przez człowieka lub zautomatyzowane, które zwiększa wykładniczą wartość przedsiębiorstwa, wprowadzając do rozpoznanego wzorca informacje o wartości dodanej, których wcześniej nie można było osiągnąć. [ niejasne ]
Struktura wydarzenia
Zdarzenie może składać się z dwóch części, nagłówka zdarzenia i treści zdarzenia. Nagłówek zdarzenia może zawierać informacje, takie jak nazwa zdarzenia, sygnatura czasowa zdarzenia i typ zdarzenia. Treść zdarzenia zawiera szczegółowe informacje o wykrytej zmianie stanu. Treści zdarzenia nie należy mylić ze wzorcem lub logiką, którą można zastosować w reakcji na wystąpienie samego zdarzenia.
Warstwy przepływu zdarzeń
Architektura sterowana zdarzeniami może być zbudowana na czterech warstwach logicznych, począwszy od wyczucia zdarzenia (tj. znaczącego stanu czasowego lub faktu), poprzez stworzenie jego technicznej reprezentacji w postaci struktury zdarzenia, a skończywszy na -pusty zestaw reakcji na to zdarzenie.
Producent wydarzeń
Pierwszą warstwą logiczną jest producent zdarzenia, który wyczuwa fakt i przedstawia go jako komunikat o zdarzeniu. Na przykład producentem zdarzenia może być klient poczty e-mail, system handlu elektronicznego, agent monitorujący lub jakiś rodzaj czujnika fizycznego.
Konwersja danych zebranych z tak różnorodnego zestawu źródeł danych do jednej znormalizowanej formy danych do oceny jest ważnym zadaniem w projektowaniu i wdrażaniu tej pierwszej warstwy logicznej. Biorąc jednak pod uwagę, że zdarzenie jest ramą silnie deklaratywną, można łatwo zastosować dowolne operacje informacyjne, eliminując w ten sposób potrzebę wysokiego poziomu standaryzacji. [ potrzebne źródło ]
Kanał wydarzenia
To jest druga warstwa logiczna. Kanał zdarzeń to mechanizm propagujący informacje zebrane z generatora zdarzeń do mechanizmu zdarzeń lub ujścia. Może to być połączenie TCP/IP lub dowolny typ pliku wejściowego (płaski, format XML, e-mail itp.). Jednocześnie można otworzyć kilka kanałów zdarzeń. Zwykle, ponieważ mechanizm przetwarzania zdarzeń musi przetwarzać je w czasie zbliżonym do rzeczywistego, kanały zdarzeń będą odczytywane asynchronicznie. Zdarzenia są przechowywane w kolejce, czekając na późniejsze przetworzenie przez mechanizm przetwarzania zdarzeń.
Silnik przetwarzania zdarzeń
Silnik przetwarzania zdarzeń to warstwa logiczna odpowiedzialna za identyfikację zdarzenia, a następnie wybranie i wykonanie odpowiedniej reakcji. Może również wywołać szereg twierdzeń. Na przykład, jeśli zdarzenie, które pojawia się w mechanizmie przetwarzania zdarzeń, dotyczy niskiego poziomu produktu o identyfikatorze, może to wywołać takie reakcje, jak „Zamów identyfikator produktu” i „Powiadom personel”.
Dalsza aktywność sterowana zdarzeniami
Jest to warstwa logiczna, w której pokazane są konsekwencje zdarzenia. Można to zrobić na wiele różnych sposobów i form; np. wiadomość e-mail jest wysyłana do kogoś, a aplikacja może wyświetlać jakieś ostrzeżenie na ekranie. W zależności od poziomu automatyzacji zapewnianego przez ujście (silnik przetwarzania zdarzeń) dalsze działania mogą nie być wymagane.
Style przetwarzania zdarzeń
Istnieją trzy ogólne style przetwarzania zdarzeń: proste, strumieniowe i złożone. Te trzy style są często używane razem w dojrzałej architekturze sterowanej zdarzeniami.
Proste przetwarzanie zdarzeń
Proste przetwarzanie zdarzeń dotyczy zdarzeń, które są bezpośrednio związane z określonymi, mierzalnymi zmianami stanu. W prostym przetwarzaniu zdarzeń ma miejsce godne uwagi zdarzenie, które inicjuje dalsze działania. Proste przetwarzanie zdarzeń jest powszechnie stosowane do kierowania przepływem pracy w czasie rzeczywistym, zmniejszając w ten sposób czas opóźnienia i koszty.
Na przykład proste zdarzenia mogą być tworzone przez czujnik wykrywający zmiany ciśnienia w oponach lub temperatury otoczenia. Nieprawidłowe ciśnienie w oponach samochodu wygeneruje proste zdarzenie z czujnika, które uruchomi żółte światło informujące kierowcę o stanie opony.
Przetwarzanie strumienia zdarzeń
W przetwarzaniu strumienia zdarzeń (ESP) zdarzają się zarówno zwykłe, jak i godne uwagi zdarzenia. Zwykłe zdarzenia (zamówienia, transmisje RFID) są sprawdzane pod kątem rozpoznawalności i przesyłane strumieniowo do subskrybentów informacji. Przetwarzanie strumienia zdarzeń jest powszechnie stosowane do kierowania przepływem informacji w przedsiębiorstwie i wokół niego w czasie rzeczywistym, co umożliwia podejmowanie decyzji w czasie.
Złożone przetwarzanie zdarzeń
Przetwarzanie złożonych zdarzeń (CEP) umożliwia uwzględnienie wzorców prostych i zwykłych zdarzeń w celu wywnioskowania, że wystąpiło złożone zdarzenie. Złożone przetwarzanie zdarzeń ocenia zbieżność zdarzeń, a następnie podejmuje działanie. Zdarzenia (godne uwagi lub zwyczajne) mogą łączyć różne typy zdarzeń i występować przez długi okres czasu. Korelacja zdarzeń może być przyczynowa, czasowa lub przestrzenna. CEP wymaga zastosowania zaawansowanych interpretatorów zdarzeń, definiowania i dopasowywania wzorców zdarzeń oraz technik korelacji. CEP jest powszechnie używany do wykrywania anomalii biznesowych, zagrożeń i możliwości oraz reagowania na nie.
Przetwarzanie zdarzeń online
Przetwarzanie zdarzeń online (OLEP) wykorzystuje asynchroniczne rozproszone dzienniki zdarzeń do przetwarzania złożonych zdarzeń i zarządzania trwałymi danymi. OLEP pozwala niezawodnie komponować powiązane zdarzenia złożonego scenariusza w heterogenicznych systemach. Dzięki temu umożliwia bardzo elastyczne wzorce dystrybucji z wysoką skalowalnością i zapewnia dużą spójność. Nie może jednak zagwarantować górnej granicy czasu przetwarzania.
Ekstremalnie luźne sprzęgło i dobrze rozłożone
Architektura sterowana zdarzeniami jest wyjątkowo luźno powiązana i dobrze rozłożona. Wielka dystrybucja tej architektury istnieje, ponieważ wydarzeniem może być prawie wszystko i może istnieć prawie wszędzie. Architektura jest niezwykle luźno powiązana, ponieważ samo zdarzenie nie zna konsekwencji swojej przyczyny. Np. jeśli mamy system alarmowy, który rejestruje informacje, kiedy drzwi wejściowe się otwierają, same drzwi nie wiedzą, że system alarmowy doda informację, kiedy drzwi się otworzą, tylko że drzwi zostały otwarte.
Semantic Coupling i dalsze badania
Architektury sterowane zdarzeniami mają luźne powiązania w przestrzeni, czasie i synchronizacji, zapewniając skalowalną infrastrukturę do wymiany informacji i rozproszonych przepływów pracy. Jednak architektury zdarzeń są ściśle powiązane, poprzez subskrypcje i wzorce zdarzeń, z semantyką podstawowego schematu zdarzeń i wartości. Wysoki stopień semantycznej heterogeniczności zdarzeń w dużych i otwartych wdrożeniach, takich jak inteligentne miasta i sieć czujników, utrudnia opracowywanie i utrzymywanie systemów opartych na zdarzeniach. , aktywnym obszarem badań jest wykorzystanie przybliżonego semantycznego dopasowywania zdarzeń.
Implementacje i przykłady
Jawa huśtawka
Java Swing API jest oparta na architekturze sterowanej zdarzeniami . Działa to szczególnie dobrze z motywacją stojącą za Swing, aby zapewnić komponenty i funkcje związane z interfejsem użytkownika. Interfejs API wykorzystuje konwencję nomenklatury (np. „ActionListener” i „ActionEvent”) w celu powiązania i uporządkowania zagadnień związanych ze zdarzeniami. Klasa, która musi być świadoma konkretnego zdarzenia, po prostu implementuje odpowiedni detektor, nadpisuje odziedziczone metody, a następnie jest dodawana do obiektu, który uruchamia zdarzenie. Bardzo prostym przykładem może być:
klasa publiczna FooPanel rozszerza JPanel implementuje ActionListener { public FooPanel () { super (); JButton btn = nowy JButton ( "Kliknij mnie!" ); btn . addActionListener ( to ); to . dodaj ( btn ); } @Override public void actionPerformed ( ActionEvent ae ) { System . na zewnątrz println ( "Kliknięto przycisk!" ); } }
Alternatywnie, innym wyborem implementacji jest dodanie słuchacza do obiektu jako klasy anonimowej , a tym samym użycie notacji lambda (od wersji Java 1.8). Poniżej znajduje się przykład.
klasa publiczna FooPanel rozszerza JPanel { publiczny FooPanel () { super (); JButton btn = nowy JButton ( "Kliknij mnie!" ); btn . addActionListener ( ae -> System . out . println ( "Kliknięto przycisk!" )); to . dodaj ( btn ); } }
JavaScript
(() => { 'use strict' ; class EventEmitter { konstruktor () { this . zdarzenia = nowa mapa (); } on ( zdarzenie , słuchacz ) { if ( typ słuchacza ! = = 'funkcja' ) { wyrzuć nowy błąd typu ( „Odbiornik musi być funkcją” ); } niech słuchacze = this . zdarzenia . get ( zdarzenie ); if ( ! słuchacze ) { słuchacze = nowy zestaw (); this . zdarzenia . zestaw ( zdarzenie , słuchacze ); } słuchacze .add ( słuchacz ); zwróć to ; } off ( zdarzenie , słuchacz ) { if ( ! argumenty . długość ) { to . zdarzenia . wyczyść () ; } else if ( argumenty . długość === 1 ) { to . zdarzenia . usuń ( zdarzenie ); } else { const słuchacze = to . zdarzenia . pobierz ( zdarzenie ); if ( słuchacze ) { słuchacze . usuń ( słuchacz ); } } zwróć to ; } emituj ( zdarzenie , ... argumenty ) { const słuchacze = to.zdarzenia.get ( zdarzenie ) ; if ( słuchacze ) { for ( niech słuchacz słuchaczy ) { słuchacz.zastosuj ( to , argumenty ) ; } } zwróć to ; } } } to.EmiterZdarzeń = EmiterZdarzeń ; } ) ( ) ; _ _
Stosowanie:
const zdarzenia = nowy EventEmitter (); wydarzenia . on ( 'foo' , () => { konsola . log ( 'foo' ); }); wydarzenia . emitować ( „foo” ); // Drukuje zdarzenia „foo” . wyłączone ( 'foo' ); wydarzenia . emitować ( „foo” ); // Nic się nie stanie
Pascal obiektowy
Zdarzenia są jednym z podstawowych elementów języka Object Pascal . Stosowany jest tu model uni-cast (one-to-one), czyli nadawca wysyła informacje tylko do jednego odbiorcy. To ograniczenie ma tę zaletę, że nie wymaga specjalnego detektora zdarzeń. Samo zdarzenie jest wskaźnikiem do metody w innym obiekcie. Jeśli wskaźnik nie jest pusty, gdy wystąpi zdarzenie, wywoływana jest procedura obsługi zdarzenia. Zdarzenia są często używane w klasach obsługujących GUI. Nie jest to jednak jedyny obszar zastosowań wydarzeń. Poniższy kod jest przykładem użycia zdarzeń:
0
0
jednostka MojaKlasaNiestandardowa ; interfejs używa klas ; wpisz { definicję własnego zdarzenia} TAccidentEvent = procedura ( Sender : TObject ; const AValue : Integer ) obiektu ; TMyCustomObject = class ( TObject ) private FData : Integer ; // przykład prostego pola w klasie FOnAccident : TAccidentEvent ; // zdarzenie - referencja do metody w jakimś obiekcie FOnChange : TNotifyEvent ; // zdarzenie - odwołanie do metody w jakiejś procedurze obiektowej SetData ( Value : Integer ) ; // metoda ustawiająca wartość pola w procedurze chronionej klasą DoAccident ( const AValue : Integer ) ; wirtualny ; // metoda generująca zdarzenie na podstawie własnej procedury definicji DoChange ; // metoda generująca zdarzenie na podstawie definicji z biblioteki VCL konstruktor publiczny Create ; wirtualny ; // konstruktor klasy destruktor Destroy ; zastąpić ; // destruktor klasy opublikowany właściwość Data : TAccidentEvent read FData write SetData ; // deklaracja właściwości w klasie property OnAccident : TAccidentEvent read FOnAccident write FOnAccident ; // wystawienie zdarzenia poza właściwość klasy OnChange : TNotifyEvent read FOnChange write FOnChange ; // wystawienie zdarzenia poza procedurę klasową MultiplyBy ( const AValue : Integer ) ; // metoda używająca własnej definicji końca zdarzenia ; konstruktor implementacji TMyCustomObject . Utwórz ; rozpocznij FData := ; koniec ; destruktor TMyCustomObject . zniszczyć ; rozpocznij FData := ; odziedziczone Zniszcz ; koniec ; procedura TMyCustomObject . DoAccident ( const AValue : Integer ) ; rozpocznij jeśli Assigned ( FOnAccident ) następnie FOnAccident ( Self , AValue ) ; koniec ; procedura TMyCustomObject . Zmień ; rozpocznij , jeśli przypisano ( FOnChange ), a następnie FOnChange ( self ) ; koniec ; procedura TMyCustomObject . Pomnóż przez ( const AValue : Integer ) ; rozpocząć FData := FData * AValue ; jeśli FData > 1000000 to DoAccident ( FData ) ; koniec ; procedura TMyCustomObject . SetData ( wartość : liczba całkowita ) ; rozpocznij jeśli FData <> Wartość następnie rozpocznij FData := Wartość ; Zmień ; koniec ; koniec .
Utworzona klasa może być używana w następujący sposób:
... procedura TMyForm . ShowCustomInfo ( Sender : TObject ) ; rozpocznij , jeśli nadawcą jest TMyCustomObject, a następnie ShowMessage ( „Dane uległy zmianie”. ) ; koniec ; procedura TMyForm . PerformAcident ( nadawca : TObject ; const AValue : liczba całkowita ) ; rozpocznij, jeśli nadawcą jest TMyCustomObject, a następnie ShowMessage ( „Dane przekroczyły 1000000! Nowa wartość to: „ + AValue . ToString ) ; koniec ; ... {deklaracja zmiennej, która jest obiektem określonej klasy} var LMyObject : TMyCustomObject ; ... {tworzenie obiektu} LMyObject := TMyCustomObject . Utwórz ; ... {przypisywanie metod do zdarzeń} LMyObject . OnChange := Mój formularz . PokażInformacjeCustom ; LMójObiekt . Przy wypadku := Mój formularz . PerformAcident ; ... {usunięcie obiektu, gdy nie jest już potrzebny} LMyObject . za darmo ; ...
Zobacz też
- Programowanie sterowane zdarzeniami
- Usługa przesyłania wiadomości oparta na procesach
- Architektura zorientowana na usługi
- SOA sterowana zdarzeniami
- Architektura oparta na przestrzeni
- Złożone przetwarzanie zdarzeń
- Przetwarzanie strumienia zdarzeń
- Towarzystwo Techniczne ds. Przetwarzania Zdarzeń
- Etapowa architektura sterowana zdarzeniami (SEDA)
- Wzór reaktora
- Autonomiczna praca peryferyjna
Artykuły
- Artykuł definiujący różnice między EDA i SOA: Jak EDA rozszerza SOA i dlaczego jest to ważne autorstwa Jacka van Hoofa.
- Rzeczywisty przykład wydarzeń biznesowych przebiegających w architekturze SOA: SOA, EDA i CEP — zwycięska kombinacja autorstwa Udi Dahana.
- Artykuł opisujący pojęcie danych o zdarzeniach: Analityka dla hakerów, jak myśleć o danych o zdarzeniach autorstwa Michelle Wetzler. (Archiwum internetowe)