Architektura wydarzeń
Architektura wydarzeń (EDA)
1) Co jest wydarzeniem i dlaczego EDA
Zdarzenie - niezmienny fakt, który wystąpił już w domenie („Pla, zweryfikowany”, „Wychwytywany”). EDA buduje integracje wokół publikacji tych faktów i reakcji na nie:- słaba łączność usług,
- skalowanie konsumentów niezależnie,
- powtórzenie/przegrupowanie projekcji,
- przejrzysty audyt.
EDA nie anuluje synchronicznych interfejsów API - uzupełnia je poprzez wprowadzenie zależności między usługami do warstwy asynchronicznej.
2) Rodzaje zdarzeń
Domena: istotne fakty biznesowe ( Placed, BonusGranted).
Integracja: „migawki „/zmiany dla systemów zewnętrznych (Na bieżąco Aktualizowane, Portfel Zmieniono).
Techniczna: cykl życia i telemetria (bicie serca, fiasko).
Polecenia (nie zdarzenia, ale w pobliżu): instrukcje „do X” (CapturePayment).
Zalecenie: zdarzenia domeny są podstawowe; integrację tworzą prognozy dla konkretnych konsumentów.
3) Umowy i schematy imprez
Сбева: Avro/Protobuf/JSON Schema + Schema Registry; strategia kompatybilności: „BACKWARD” dla ewolucji konsumentów, „FULL” dla tematów krytycznych.
CloudEvents (id, source, type, time, subject, datacontenttype) - jednolite nagłówki.
Wymagane metadane: 'event _ id' (ULID/UUID),' occurred _ at ',' manufacturer ',' schema _ version ',' correlation _ id'/' causation _ id', 'idempotence _ key'.
Wersioning: pola dodawane, zakaz zmiany nazwy/przerw semantycznych; nowe typy - nowe tematy/typy.
json
{
"type":"record","name":"PaymentCaptured","namespace":"events.v1",
"fields":[
{"name":"event_id","type":"string"},
{"name":"occurred_at","type":{"type":"long","logicalType":"timestamp-micros"}},
{"name":"payment_id","type":"string"},
{"name":"amount","type":{"type":"bytes","logicalType":"decimal","precision":18,"scale":2}},
{"name":"currency","type":"string"},
{"name":"player_id","type":"string"}
]
}
4) Dostawa, zamówienie i spójność
Co najmniej raz jako domyślny → potrzebna jest idempotencja obsługi.
Zamówienie: gwarantowane w ramach strony (Kafka) lub kolejki (RabbitMQ), ale mogą być złamane przez rekolekcje; klucz zdarzenia musi odzwierciedlać granulat domeny (na przykład 'player _ id').
Spójność: w przypadku pieniędzy/pożyczek - wyłącznie poprzez czasopisma/sagi/rekompensaty; unikać LWW.
Model czytania: Projekcje i bufory mogą być ostatecznie - pokaż „aktualizację w toku”... i użyj strategii RNOT dla ścisłych ścieżek.
5) Outbox/Inbox CDC
Outbox: serwis zapisuje fakt do swojej bazy danych i do tabeli wyników w jednej transakcji → pracownik publikuje do autobusu.
Skrzynka odbiorcza: Zdarzenie _ id 'z wynikiem przetwarzania w sklepach konsumenckich do deduplikacji.
CDC (Change Data Capture): przepływ zmian z bazy danych (binlog/WAL) do autobusu w celu budowy integracji bez zmian aplikacji.
Idempotencja: przetwarzanie przez 'idempotence _ key '/' event _ id', nie zmienia świata zewnętrznego, dopóki nie zostanie ustalone.
6) CQRS А Event Sourcing
CQRS: oddzielny model zapisu i projekcje odczytu; projekcje są wykonane z wydarzeń i może opóźnić.
Event Sourcing: stan zbiorczy = rollup jego zdarzeń. Plusy: pełny audyt/powtórka; minusy: złożoność migracji/schematów/migawek.
Praktyka: ES - nie wszędzie, ale gdzie historia i rekompensaty są ważne; CQRS - prawie zawsze w EDA.
7) Sagi: Orkiestra i choreografia
Orkiestra: koordynator wysyła polecenia i czeka na wydarzenia reagowania; wygodne dla złożonych procesów (KYC → Depozyt → Bonus).
Choreografia: usługi reagują na wzajemne wydarzenia; łatwiejsze, ale trudniejsze do namierzenia.
Zawsze określaj odszkodowania i terminy kroków.
8) Projektowanie topologii (Kafka/RabbitMQ)
Kafka
Temat na zdarzenie domeny: 'płatności. schwytany. v1 ',' gracze. zweryfikowany. v1 ".
Klucz podziału: 'player _ id'/' wallet _ id' - gdzie kolejność jest ważna.
"powtórzenie. współczynnik = 3 ',' min. insync. repliki = 2 ', producent' acks = all '.
Zatrzymanie: według czasu (np. 7-90 dni) i/lub zagęszczenie (ostatni stan według klucza).
Tematy dla retry i DLQ z backoff.
RabbitMQ
Wymiana: płatności "temat "/" bezpośrednie", klucz routingu ". schwytany. v1 ".
Dla szerokiego wentylatora - 'temat' + kilka kolejek; dla RPC/commands - oddzielne kolejki.
Kolejki kworum dla HA; TTL + wymiana martwych listów na przekaźniki.
9) Obserwowalność i SLO EDA
SLI/SLO:- Opóźnienie końcowe (occurred_at → przetworzone): p50/p95/p99.
- Lag/wiek: opóźnienie konsumenta (opóźnienie konsumenta Kafka, wiek zaległości królika).
- Wydawnictwo/przetwarzanie przepustowości.
- Wskaźnik DLQ i odsetek powtórzeń.
- Sukces transakcji biznesowych (np. "depozyt potwierdzony ≤ 5c').
- Korelacja zdarzeń poprzez 'trace _ id'/' correlation _ id' (OTel).
- Instancje od wyrównania → metryki.
- Deski rozdzielcze „Producent → Broker → Konsument” z nagłośnieniem.
10) Powtórka, retencja i zasypka
Powtórz, aby odbudować projekcje/naprawić błędy: przejść do nowej projekcji/przestrzeni, a następnie przełączyć odczyt.
Zachowanie: Wymogi prawne/biznesowe (RODO/PCI); pola wrażliwe - szyfrowanie i/lub tokenizacja.
Backfill: jednorazowe tematy/kolejki, wyczyścić limity RPS, aby uniknąć uciskania prod.
11) Bezpieczeństwo i zgodność
TLS w tranzycie, mTLS dla klientów wewnętrznych.
Autoryzacja: per-topic/per-exchange ACL; wielozadaniowość poprzez przestrzeń nazw/vhost.
PII: zminimalizować pola w zdarzeniu; metadane koperty oddzielnie, ładunki użytkowe zaszyfrowane w razie potrzeby.
Sprawdź dostęp do wydarzeń, zabraniaj „wszechmocnych” kluczy.
Zasady zachowania i prawa do usuwania (RODO): przechowywanie odniesień do danych lub zdarzeń nagrobkowych oraz usuwanie w projekcjach.
12) Badanie w EDA
Testy umowne: konsumenci potwierdzają swoje oczekiwania wobec systemów (kierowanych przez konsumentów).
Testy powtórne: uruchom próbkowanie historyczne poprzez nową wersję obsługi/schematu.
Scenariusze chaosu: opóźnienie/utrata brokera, spadek węzła, opóźnienie konsumenckie → SLO pozostają w obrębie.
Dym w CI: krótki rurociąg końcowy na tematy czasowe.
13) Migracja „integracji CRUD → EDA”
1. Identyfikacja faktów domeny.
2. Wbuduj skrzynkę zewnętrzną w usługi źródłowe.
3. Publikuj minimalne zdarzenia domeny i podłącz projekcje 1-2.
4. Stopniowo wyłącza synchroniczne integracje punktowe, zastępując je subskrypcjami.
5. Wpisz rejestr schematu i politykę zgodności.
6. Rozszerzenie zdarzeń dodatkowych o pola; przerwy - tylko przez nowe typy.
14) Anty-wzory
Wydarzenia = „DTO API” (zbyt gruby, zależny od modelu wewnętrznego) - złamać konsumentów.
Brak rejestru schematu i kompatybilności - „kruche” integracje.
Publikowanie z kodu i pisanie do bazy danych nie jest atomowe (brak skrzynki zewnętrznej) - tracisz zdarzenia.
„Dokładnie raz wszędzie” - wysoka cena bez korzyści; lepiej przynajmniej raz + idempotencja.
Jeden „uniwersalny” klucz podziału → gorąca partycja.
Powtórz prosto do projekcji produkcji - łamie SLO online.
15) Lista kontrolna realizacji (0-45 dni)
0-10 dni
Identyfikacja zdarzeń domeny i ich kluczy (granulki porządku).
Wdrożyć rejestr schematu i zatwierdzić strategię kompatybilności.
Dodaj skrzynkę odbiorczą/skrzynkę odbiorczą do 1-2 usług; minimalna koperta CloudEvents.
11-25 dni
Wprowadź retry/DLQ, backoff, idempotencję obsługujących.
Deski rozdzielcze: lag/age/end-to-end; ostrzeżenia o prędkości oparzenia.
Dokumentacja zdarzeń (katalog), właściciele i procesy przeglądu schematu.
26-45 dni
Powtórzenie/przegrupowanie pierwszej projekcji; runbook replay i backfill.
Polityka bezpieczeństwa (TLS, ACL, PII), zatrzymywanie, procedury RODO.
Regularny chaos i dni gry dla maklera i konsumentów.
16) Wskaźniki zapadalności
100% zdarzeń domeny są opisane przez schematy i zarejestrowane.
Skrzynka odbiorcza/skrzynka odbiorcza obejmuje wszystkich producentów/konsumentów Tier-0/1.
SLO: p95 opóźnienia końcowe i opóźnienia konsumenckie w zakresie celów ≥ 99%.
Powtórka/zasypka są wykonalne bez przestojów; istnieją zweryfikowane książki startowe i.
Wersioning: nowe pola - bez łamania; starzy konsumenci nie spadają.
Bezpieczeństwo: TLS + mTLS, ACL na temat, dzienniki dostępu, zasady PII/retencji.
17) Mini snajpery
Producent Kafka (wiarygodna publikacja, pomysły):properties acks=all enable.idempotence=true max.in.flight.requests.per.connection=1 compression.type=zstd linger.ms=5
Opiekun konsumentów (idempotencja, pseudokoda):
python if inbox.contains(event_id): return # дедуп process(event) # побочные эффекты детерминированы inbox.commit(event_id) # atomically with side-effect commit_offset()
RabbitMQ Retry poprzez DLX (idea):
- 'kolejka: zadania' → na nack → zadania DLX '. ponowna próba. 1m' (TTL = 60s) → powrót do 'tasks'; dalej "5m/15m'.
18) Wniosek
EAO zmienia integrację w przepływ faktów biznesowych z jasnymi umowami i zarządzaną spójnością. Zbuduj fundament: schematy + rejestr, skrzynka odbiorcza/skrzynka odbiorcza, klucze zamówienia, idempotent handlers, SLO i obserwowalność, bezpieczne zatrzymywanie i powtarzanie. Wtedy wydarzenia staną się twoim „źródłem prawdy” do skalowania, analizy i nowych funkcji - bez kruchych połączeń i nocnych migracji.