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ż

Artykuły

Linki zewnętrzne