Hændelsesdrevne arkitekturer
Udforsk principperne i og implementeringen af hændelsesdrevne systemer ved hjælp af message queues og brokers i Clojure.
Hændelsesdrevne arkitekturer er en gratis Funktionel programmering i Clojure og backendudvikling på JVM-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Funktionel programmering i Clojure og backendudvikling på JVM, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Funktionel programmering i Clojure og backendudvikling på JVM-kurset indeholder 4 lektioner i alt.
Introduktion til hændelsesdrevne systemer
Hændelsesdrevet arkitektur (EDA) er et designmønster, hvor komponenter kommunikerer ved at udsende og reagere på hændelser. I stedet for at kalde funktioner direkte publicerer dele af systemet hændelser, når der sker noget interessant.
Denne tilgang bidrager til at skabe systemer, der er:
- Løst koblede: Komponenterne behøver ikke at kende hinanden.
- Skalerbare: Du kan nemt tilføje flere forbrugere uden at ændre producenterne.
- Modstandsdygtige: Fejl i én del er mindre tilbøjelige til at få hele systemet til at bryde sammen.
Hændelser: Den centrale meddelelse
En hændelse er en registrering af noget, der er sket. Det er normalt en lille, uforanderlig meddelelse, der indeholder data om hændelsen, men ikke kommandoen til at udføre en handling.
Tænk på det som en avisoverskrift: "Bruger oprettet" eller "Ordre afgivet".
Vigtige egenskaber:
- Faktum: Den beskriver noget, der er sket.
- Uforanderlig: Når en hændelse først er publiceret, ændres den ikke.
- Informativ: Indeholder relevante data (f.eks. bruger-ID og tidsstempel).
Roller: Producenter og forbrugere
I en EDA er der to hovedroller:
- Producenter: Det er komponenter, der opretter og publicerer hændelser. Når en bruger tilmelder sig, kan "User Service" producere hændelsen "User Signed Up".
- Forbrugere: Det er komponenter, der abonnerer på hændelser og reagerer på dem. En "Welcome Email Service" kan forbruge hændelser af typen "User Signed Up" for at sende en velkomstmail.
Producenten er ligeglad med, hvem der forbruger hændelsen, og forbrugerne er ligeglade med, hvem der producerede den. Det muliggør en effektiv løs kobling!
Meddelelsesmæglere: Knudepunktet
Hvordan finder producenter og forbrugere hinanden? Det er her, en meddelelsesmægler kommer ind i billedet. En mægler fungerer som mellemled: Den modtager hændelser fra producenter og leverer dem til interesserede forbrugere.
Den tilbyder:
- Løs kobling: Producenter og forbrugere kommunikerer ikke direkte.
- Vedholdenhed: Hændelser kan gemmes, indtil forbrugerne er klar.
- Routing: Sender hændelser til de korrekte forbrugere baseret på regler.
Almindelige eksempler omfatter RabbitMQ, Apache Kafka og AWS SQS.
Clojure og meddelelsesbiblioteker
Clojure egner sig godt til hændelsesdrevne systemer på grund af fokusset på uforanderlighed og samtidighed. Vi bruger ofte dedikerede klientbiblioteker til at interagere med meddelelsesmæglere.
Til RabbitMQ er langohr et populært valg i Clojure. Det tilbyder en enkel API til at oprette forbindelse samt publicere og forbruge meddelelser.
Lad os se på, hvordan man opsætter en grundlæggende forbindelse og publicerer en hændelse ved hjælp af langohr (konceptuelt, da en komplet opsætning er for omfattende til et lille kodestykke).
Publicering af en hændelse
For at publicere en hændelse opretter vi forbindelse til meddelelsesmægleren og sender vores hændelsesdata til en bestemt exchange. En exchange fungerer som et postkontor, der dirigerer meddelelser.
Her er et forenklet eksempel på publicering af hændelsen "user.signed-up" til en topic-exchange med navnet "events":
(ns coddykit.producer
(:require [langohr.core :as lc]
[langohr.channel :as lch]
[langohr.exchange :as le]
[langohr.basic :as lb]
[cheshire.core :as json]))
(defn -main [& args]
(let [conn (lc/connect {:host "localhost"})
ch (lch/open conn)
event-data {:user-id 123 :username "Alice" :timestamp (str (java.time.Instant/now))}]
(le/declare ch "events" "topic" {:durable true}) ; Declare topic exchange
(lb/publish ch "events" "user.signed-up" (json/generate-string event-data)
{:content-type "application/json"})
(println "Published user.signed-up event: " event-data)
(lc/close ch)
(lc/close conn)))Forbrug af en hændelse
Forbrugere opretter forbindelse til mægleren og erklærer en kø. Derefter binder de denne kø til en exchange med en routing-nøgle for at modtage bestemte typer hændelser. Når en hændelse ankommer, behandler en handlerfunktion den.
Dette eksempel viser en forbruger, der lytter efter hændelser af typen "user.signed-up":
(ns coddykit.consumer
(:require [langohr.core :as lc]
[langohr.channel :as lch]
[langohr.queue :as lq]
[langohr.basic :as lb]
[langohr.consumers :as lcons]
[cheshire.core :as json]))
(defn handle-message [ch metadata payload]
(let [event (json/parse-string (String. payload "UTF-8") true)]
(println "Received event: " event)
(println "User" (:username event) "signed up! Sending welcome email...")
; Acknowledge the message to remove it from the queue
(lb/ack ch (:delivery-tag metadata))))
(defn -main [& args]
(let [conn (lc/connect {:host "localhost"})
ch (lch/open conn)
queue-name "welcome-email-queue"]
(lq/declare ch queue-name {:durable true :exclusive false :auto-delete false})
(lq/bind ch queue-name "events" {:routing-key "user.signed-up"}) ; Bind to topic exchange
(println "Waiting for messages. To exit, press Ctrl+C...")
(lcons/create-default ch queue-name handle-message {:auto-ack false})
; Keep the main thread alive to listen for messages
(while true (Thread/sleep 1000))))Hvorfor EDA er effektivt
Ud over simpel løs kobling tilbyder EDA betydelige fordele i komplekse systemer:
- Skalerbarhed: Tilføj nemt flere forbrugere, der kan behandle hændelser parallelt, eller skalér producenter uafhængigt.
- Modstandsdygtighed: Hvis en forbruger svigter, holder meddelelsesmægleren hændelserne, indtil forbrugeren er tilbage, så datatab undgås.
- Revisionsspor: Hændelser kan logges, så der oprettes et tydeligt revisionsspor over systemets aktiviteter.
- Behandling i realtid: Reagér øjeblikkeligt på ændringer på tværs af forskellige tjenester.
Det er et grundlæggende mønster for mikrotjenester og distribuerede systemer.
Begrebet Event Sourcing
Et beslægtet, effektivt begreb er Event Sourcing. I stedet for at gemme en applikations aktuelle tilstand gemmer du alle ændringer som en sekvens af uforanderlige hændelser.
Applikationens tilstand kan derefter genskabes ved at afspille disse hændelser igen. Det giver en komplet historisk registrering og forenkler kompleks tilstandshåndtering i visse scenarier.
Selvom begreberne er beslægtede, fokuserer EDA på kommunikation mellem tjenester, mens Event Sourcing fokuserer på, hvordan en enkelt tjeneste håndterer sin egen tilstand.
Hurtigt tjek: EDA-principper
Overvej et system, hvor en bruger afgiver en ordre. Hvilket af følgende udsagn beskriver bedst en hændelsesdrevet tilgang?
Opsummering og næste trin
Godt klaret! Du har udforsket grundprincipperne i hændelsesdrevne arkitekturer.
- Vi lærte, at hændelser er uforanderlige fakta om ting, der er sket.
- Producenter udgiver hændelser, og forbrugere reagerer på dem.
- En meddelelsesbroker faciliterer denne kommunikation og sikrer afkobling og robusthed.
- Clojure-biblioteker som
langohrgør det nemt at integrere med brokere som RabbitMQ.
EDA er et vigtigt mønster til opbygning af skalerbare, robuste og afkoblede backend-systemer. Bliv ved med at øve dig i meddelelsessystemer for at styrke din forståelse!
Lær Clojure med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 12
- Lektioner
- 48
Ofte stillede spørgsmål
Er lektionen “Hændelsesdrevne arkitekturer” gratis?
Ja — hele teksten til “Hændelsesdrevne arkitekturer” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Funktionel programmering i Clojure og backendudvikling på JVM-kurset, skal du opgradere til CoddyKit PRO. Funktionel programmering i Clojure og backendudvikling på JVM-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Hændelsesdrevne arkitekturer”?
Udforsk principperne i og implementeringen af hændelsesdrevne systemer ved hjælp af message queues og brokers i Clojure. Du øver dig i Funktionel programmering i Clojure og backendudvikling på JVM med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Funktionel programmering i Clojure og backendudvikling på JVM?
Der kræves ingen tidligere erfaring. Funktionel programmering i Clojure og backendudvikling på JVM på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Hændelsesdrevne arkitekturer”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Funktionel programmering i Clojure og backendudvikling på JVM-lektion?
Ja. Alle Funktionel programmering i Clojure og backendudvikling på JVM-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Opbygning af en RESTful API
- Hændelsesdrevne arkitekturer
- Systemdesign og skaleringsmønstre
- Godkendelse og autorisation