Problem: heç kimin görə bilmədiyi axın

Komanda sinxron checkout-u hadisələrlə əvəz edir. OrderPlaced ödənişi işə salır, ödəniş PaymentCaptured yayır, inventar reaksiya verir, çatdırılma inventara reaksiya verir, bildiriş servisi isə hamısını dinləyir. Sistem miqyaslanır, servislər müstəqil deploy olunur. Altı ay sonra müştəri "ödədim, amma heç nə göndərilmədi" yazır və beş kod bazasını və üç dashboard-u oxumadan hansı servisin işi buraxdığını demək mümkün olmur.

Event-driven arxitektura (EDA) güclü alətdir, amma mürəkkəbliyi call stack-dən zamana və topologiyaya daşıyır. Bu məqalə nəyi aldığınızı və nəyə görə ödədiyinizi bilmək haqqındadır.

Event və command fərqli şeylərdir

  • Command bir qəbuledicinin ünvanına sorğudur: CapturePayment. Rədd edilə bilər və göndərən nəticəyə əhəmiyyət verir.
  • Event artıq baş vermiş faktın bəyanıdır: PaymentCaptured. Yayımlayan kimin dinlədiyini bilmir və onu rədd etmək olmur.

Adlandırma vacibdir, çünki asılılığı üzə çıxarır. Servis topic-ə SendWelcomeEmail göndərirsə, bu, event libası geyinmiş command-dır: yayımlayan konkret davranış gözləyir. Keçmiş zamanda faktlara (CustomerRegistered) üstünlük verin və e-poçt servisi onlarla nə edəcəyini özü həll etsin.

Event-lərin ölçüsü də var. İncə bildiriş event-i yalnız id daşıyır ("sifariş 42 dəyişdi"), consumer-lər təfərrüat üçün geri müraciət edir; bu, yük və producer API-sinə asılılıq yaradır. Event-carried state transfer event-i consumer-lərə lazım olan məlumatı daşıyır, geri çağırışı aradan qaldırır, amma məlumatı kopyalayır və sxemi açıq müqaviləyə çevirir.

Choreography və orchestration

Choreography-də servislər mərkəzi koordinator olmadan bir-birinin event-lərinə reaksiya verir. Boş əlaqəlidir və iki-üç addım üçün sadədir.

Orchestration-da koordinator (saga orchestrator və ya workflow mühərriki) hər iştirakçıya nə edəcəyini deyir və bütün prosesin vəziyyətini izləyir.

Choreography:
 Order --OrderPlaced--> Payment --PaymentCaptured--> Inventory
                                                  --Reserved--> Shipping

Orchestration:
            +--> Payment
 Orchestrator --+--> Inventory      (prosesi bir yer bilir)
            +--> Shipping

Choreography-də başdan-sona axın gizli qalır: o yalnız abunəliklərin cəmində mövcuddur, ona görə "inventar rezerv edildikdən sonra ödəniş uğursuz olsa nə olur?" sualına cavab vermək çətindir. Orchestration axını aşkar və test edilə bilən edir, timeout və kompensasiya üçün bir yer verir; əvəzində mərkəzi komponent yaranır və o, "god service"-ə çevrilməməlidir. Ağlabatan qayda: kiçik və sabit axında choreography; prosesin çoxlu addımı, müddəti və ya kompensasiyaları varsa orchestration.

Paylanmış transaction olmadan çox servisli biznes əməliyyatı saga-dır: hər biri sonrakı addım uğursuz olarsa kompensasiya əməliyyatı (ödənişi qaytar, stoku burax) olan lokal transaction-lar ardıcıllığı. Kompensasiya texniki rollback yox, biznes məntiqidir və bəzi addımları ümumiyyətlə geri qaytarmaq olmur.

Eventual consistency istifadəçi interfeysinə çatır

Sifariş servisi 202 Accepted qaytarır, read model isə sonra yenilənir; ekran köhnə məlumat göstərə bilər. Əksini iddia etmək klassik şikayətə səbəb olur: "ödəyə basdım, səhifə hələ də ödənilməyib yazır".

Praktik üsullar:

  • command nəticəsində yeni resursun id-sini və vəziyyətini qaytarın ki, UI optimistik göstərə bilsin;
  • aydın "emal olunur" vəziyyəti göstərin, yekun nəticəni poll və ya push ilə çatdırın;
  • vacib yerlərdə read-your-own-writes təmin edin, məsələn, istifadəçinin növbəti oxunuşunu yazı mənbəyinə yönləndirin;
  • "pending"-i xəta yox, biznesin tam hüquqlu vəziyyəti kimi modelləşdirin.

Sxemin təkamülü

Event-lər onları yazan koddan uzun yaşayır: retention-lı topic köhnə formaları record-ları saxladığı qədər saxlayır və yeni consumer hamısını replay edə bilər. Əziyyətdən qoruyan qaydalar:

  • opsional sahələr əlavə edin; mövcud sahələrin adını və ya mənasını dəyişməyin;
  • sahə adını başqa tip və ya semantika ilə yenidən istifadə etməyin;
  • pozucu dəyişiklik qaçılmazdırsa, event tipini açıq versiyalayın (OrderPlaced.v2) və miqrasiya zamanı hər iki versiyanı işlədin;
  • uyğunluq yoxlaması olan sxem formatı (registry ilə Avro, Protobuf və ya JSON Schema) seçin və CI-da tətbiq edin;
  • consumer-ləri tanımadığı sahələri nəzərə almayan tolerant oxucu edin.
{  "eventId": "7c1f...",  "type": "OrderPlaced",  "version": 2,  "occurredAt": "2026-10-19T09:30:00Z",  "data": { "orderId": "o-42", "currency": "AZN", "total": "120.00" }}

Event axınını debug etmək və idarə etmək

Ayrılmanın qiymətini müşahidəçilik işi ilə ödəyirsiniz. Hər event header-inə correlation id qoyun və hər yerdə log edin; trace kontekstini broker vasitəsilə ötürün ki, bir trace publisher və consumer-ləri əhatə etsin; group üzrə consumer lag-ı əsas sağlamlıq siqnalı kimi izləyin; dead-letter topic-ləri görünən saxlayın. "42 nömrəli sifarişə nə oldu" sualına bir sorğu ilə cavab verməyin yolunu qurun: orchestrator-da proses vəziyyəti cədvəli və ya əlaqələndirilmiş log-lar üzrə axtarış.

Sıra və dublikatları da planlayın (delivery semantics məqaləsinə baxın): consumer-lər idempotent olmalıdır, partition-lar arasında qlobal sıra güman edən məntiq gec-tez sınacaq.

Sinxron çağırış nə vaxt daha sadədir

Çağıran davam etmək üçün cavaba ehtiyac duyursa (qiymət sorğusu, icazə yoxlaması), əməliyyat görünən bir vahid kimi uğurlu və ya uğursuz olmalıdırsa, komanda kiçikdirsə və servislər azdırsa, yaxud məlumat güclü consistency ilə lazımdırsa, birbaşa çağırış istifadə edin. Həmişə birlikdə deploy olunan və həmişə bir-birinin cavabına ehtiyac duyan iki servis arasına broker qoymaq müstəqillik olmadan mürəkkəblik alır.

Hibrid yanaşma yayğın və sağlamdır: istifadəçinin gözlədiyi kənarlarda sinxron request/response, sistemin başqa hissələrinin sonra reaksiya verdiyi faktların yayılması üçün event-lər.

Tez-tez edilən səhvlər

  • Event kimi maskalanmış command-lar yayımlamaq və konkret consumer-dən asılı olmaq.
  • Sadə sorğular da daxil olmaqla hər şey üçün event istifadə etmək.
  • Başdan-sona axını sənədləşdirmədən çoxlu servis arasında choreography.
  • Outbox əvəzinə dual write, səssiz uyğunsuzluq.
  • Event sxemlərini yerində dəyişib replay edən consumer-ləri sındırmaq.
  • İstifadəçilər şikayət edənə qədər consumer lag-a fikir verməmək.
  • Topic və ya sxemin sahibinin olmaması.

Kompromislər bir cədvəldə

CəhətQazancQiymət
AyrılmaServislər müstəqil deploy olunur və uğursuz olurGizli asılılıqlar, təsir analizi çətinləşir
ÖtürməPik yükü udur, consumer-lər miqyaslanırGecikmə çağırışla məhdudlaşmır
AuditEvent tarixçəsi replay oluna bilərSaxlama, sxem intizamı
ConsistencyLokal transaction-lar sadə qalırEventual consistency, saga, UX işi
Debuggingİzolə olunmuş komponentlərPaylanmış tracing məcburidir

Yoxlama siyahısı

  1. Hər mesaj aydın şəkildə event (fakt) və ya command (sorğu)-dur.
  2. Başdan-sona axın timeout və kompensasiyalarla sənədləşib.
  3. Hər event-də id, tip, versiya, timestamp və correlation id var.
  4. Sxem uyğunluğu avtomatik yoxlanır.
  5. Consumer-lər idempotent və naməlum sahələrə tolerantdır.
  6. UI-da dürüst pending vəziyyəti var.
  7. Lag, dead letter və axın vəziyyəti izlənir.
  8. Sinxron çağırış nəzərdən keçirilib və göstərilən səbəblə rədd edilib.

Növbəti addım