Olay Odaklı İş Akışları Oluşturma
Hizmetleri olaylar ve idempotentlik aracılığıyla koordine edin.
Olay Odaklı İş Akışları Oluşturma, CoddyKit'te ücretsiz bir PHP Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, PHP Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. PHP Academy kursu toplamda 4 dersten oluşur.
Olay Odaklı İş Akışları
Tek bir mesaj kolaydır. Birden çok hizmete yayılan iş akışı — “sipariş verildi → stoğu ayır → karttan ücret çek → gönder → bildir” — olay odaklı tasarımın değerini gösterdiği ve safça uygulandığında sorun çıkardığı yerdir.
Bu derste koreografi ile orkestrasyonu, atomik yayımlama için giden kutusu desenini, dağıtık geri alma için sagaları ve bütün yapıyı bir arada tutan yinelenen işlemlerde güvenilirliği ele alacağız.
Koreografi ve Orkestrasyon
Birden çok adımlı akışları koordine etmenin iki yolu vardır:
- Koreografi — her hizmet olaylara tepki verir ve kendi olaylarını yayımlar; merkezi bir yönetici yoktur. Gevşek bağlıdır, ancak genel akış örtüktür ve izlenmesi zordur.
- Orkestrasyon — merkezi bir koordinatör, her hizmete sırada ne yapacağını söyler. Açık ve gözlemlenebilirdir, ancak orkestratör bir bağımlılık noktasıdır.
Genel kural: Basit çoklu dağıtım için koreografi, çok sayıda sıralı adımı olan ve görünür durum gerektiren akışlar için orkestrasyon kullanın.
Olaylar ve Komutlar
Mesajlarınızı bilinçli bir şekilde adlandırın:
- Bir olay geçmişte gerçekleşmiş bir gerçeği belirtir:
OrderPlaced. Yayımcı, kimin dinlediğiyle ilgilenmez. - Bir komut, belirli bir işleyicide gelecekte gerçekleştirilecek bir eylemi ister:
ChargeCard.
Olaylar koreografiyi, komutlar orkestrasyonu yönlendirir. Terimleri karıştırmak (gizlice tek bir işleyici bekleyen bir “olay” kullanmak), gizli bağımlılıkların yaygın bir kaynağıdır.
<?php
final class OrderPlaced {
public function __construct(
public readonly string $orderId,
public readonly string $customerId,
public readonly int $amountCents,
public readonly string $occurredAt,
) {}
}
$e = new OrderPlaced('o-42', 'c-7', 1990, gmdate('c'));
echo json_encode($e), "\n";Çift Yazma Sorunu
Klasik hata şudur: Bir işleyici, veri tabanını günceller ve mesajı iki ayrı işlem olarak yayımlar. Süreç bu ikisinin arasında sona ererse bir tutarsızlık oluşur — the satır değişmiştir ama olay gönderilmemiştir veya bunun tersi olmuştur.
<?php
// BROKEN: not atomic. A crash between the two lines corrupts state.
function placeOrder(PDO $db, $broker, array $o): void {
$db->prepare('INSERT INTO orders ...')->execute($o);
// <-- crash here = row exists but no event ever published
$broker->publish('OrderPlaced', json_encode($o));
}İşlemsel Giden Kutu
Çözüm giden kutusu desenidir: Verilerinizi değiştiren aynı veri tabanı işlemi içinde olayı bir outbox tablosuna ekleyin. Ayrı bir aktarım süreci yayımlanmamış satırları okur ve bunları aracıya gönderir. Tek bir atomik işleme, çift yazma yok.
<?php
function placeOrder(PDO $db, array $o): void {
$db->beginTransaction();
$db->prepare('INSERT INTO orders (id, total) VALUES (?, ?)')
->execute([$o['id'], $o['total']]);
// Same transaction -> atomic with the business write
$db->prepare('INSERT INTO outbox (id, type, payload) VALUES (?, ?, ?)')
->execute([bin2hex(random_bytes(8)), 'OrderPlaced', json_encode($o)]);
$db->commit();
}Aktarıcı (Yayımcı)
Bir işçi, giden kutusunu yoklar (veya veri tabanı değişiklik günlüğünü CDC aracılığıyla izler), her satırı yayımlar ve ardından satırı gönderildi olarak işaretler. Aktarım süreci yayımladıktan sonra ancak işaretlemeden önce çökebileceği için kendisi de en az bir kez teslim semantiğine sahiptir — tüketiciler yinelenen işlemlerde güvenli olduğu için bu sorun değildir.
<?php
function relayOutbox(PDO $db, $broker): void {
$rows = $db->query(
'SELECT id, type, payload FROM outbox
WHERE published_at IS NULL ORDER BY created_at LIMIT 100'
)->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $r) {
$broker->publish($r['type'], $r['payload'], messageId: $r['id']);
$db->prepare('UPDATE outbox SET published_at = now() WHERE id = ?')
->execute([$r['id']]);
}
}Yinelenen İşlemlerde Güvenli Tüketiciler (Tekrar)
Hem aktarım süreci hem de aracı en az bir kez teslim kullandığından, sonraki işleyiciler yinelenen mesajlar görecektir. Her tüketici işlediği mesaj kimliğini kaydeder ve tekrarları erkenden sonlandırır — daha önce öğrendiğiniz aynı tekilleştirme denetimi, şimdi hizmet başına uygulanır.
<?php
function onOrderPlaced(PDO $db, string $messageId, array $data): void {
$db->beginTransaction();
try {
$db->prepare('INSERT INTO inbox (message_id) VALUES (?)')
->execute([$messageId]); // unique index = dedup
} catch (PDOException $e) {
$db->rollBack();
return; // already handled this message
}
reserveStock($data['orderId']);
$db->commit();
}
function reserveStock(string $id): void {}Sagalar: Dağıtık Geri Alma
Hizmetler arasında tek bir ACID işlemi açamazsınız. Bir saga, uzun süren bir akışı yerel işlemler dizisi olarak modeller; her işlemin, yaptığı işi geri alan bir telafi eylemi vardır. 3. adım başarısız olursa 2. ve 1. adımların telafi işlemlerini ters sırayla çalıştırırsınız.
Örnek: Stok ayrıldıktan sonra ödeme başarısız olursa telafi amacıyla ReleaseStock yayımlayın. Otomatik geri alma yoktur — her adım için geri alma işlemini sizin tasarlamanız gerekir.
Orkestre Edilen Saga
Bir orkestrasyon yöneticisi sagayı yürütür: başarı durumunda ilerler ve başarısızlık durumunda telafi işlemlerini gönderir. Bir çökme sonrasında devam edebilmesi için saganın durumunu kalıcı olarak saklayın.
<?php
function handleStepResult(array $saga, string $step, bool $ok, $bus): array {
if ($ok) {
$next = ['reserveStock' => 'chargeCard', 'chargeCard' => 'ship'][$step] ?? null;
if ($next) { $bus->send($next, $saga['orderId']); $saga['state'] = $next; }
else { $saga['state'] = 'completed'; }
} else {
// Run compensations in reverse for whatever already succeeded
foreach (array_reverse($saga['done']) as $s) {
$bus->send('compensate.' . $s, $saga['orderId']);
}
$saga['state'] = 'compensating';
}
return $saga;
}Uzun Akışlarda Zaman Aşımları
Bir saga adımı hiçbir zaman yanıt vermeyebilir — ödeme hizmeti çalışmıyor olabilir veya bir insan onayı hiç gelmeyebilir. Zaman aşımı olmadan saga, ayırmaları elinde tutarak sonsuza dek takılı kalır. Her adım için bir son tarih saklayın; bir zamanlayıcı süresi aşılmış sagaları tarayıp hata/telafi yolunu tetiklesin.
<?php
function reapTimedOutSagas(PDO $db, $bus): void {
$rows = $db->query(
"SELECT order_id, state FROM sagas
WHERE state NOT IN ('completed','compensating')
AND deadline_at < now()"
)->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $r) {
echo "Saga {$r['order_id']} timed out at step {$r['state']}\n";
$bus->send('saga.compensate', $r['order_id']); // trigger rollback
}
}Sürümleme ve Gözlemlenebilirlik
İş akışları yıllarca yaşar; olaylar güvenli bir şekilde evrilmelidir:
- Her olaya bir
version(veya şema) ekleyin; tüketiciler bilinmeyen yeni alanları tolere etmeli ve bir alanın mutlaka mevcut olduğunu varsaymamalıdır. - Eklemeli değişiklikleri tercih edin; mevcut bir alanın anlamını asla başka bir amaçla kullanmayın.
- Günlüklerinizde ve izlemelerinizde tek bir ticari işlemi tüm hizmetler boyunca izleyebilmek için her ileti üzerinden bir ilişkilendirme kimliği iletin.
İlişkilendirme kimlikleri olmadan, beş hizmete yayılan koreografili bir iş akışında hata ayıklamak neredeyse imkânsızdır.
<?php
$envelope = [
'type' => 'OrderPlaced',
'version' => 2,
'correlationId' => $incoming['correlationId'] ?? bin2hex(random_bytes(8)),
'occurredAt' => gmdate('c'),
'data' => ['orderId' => 'o-42'],
];
echo json_encode($envelope, JSON_PRETTY_PRINT), "\n";Hızlı Kontrol
Çift yazma sorunundan kaçınma.
Özet
Artık güvenilir, olay güdümlü iş akışları tasarlayabilirsiniz:
- Her akışın karmaşıklığına göre koreografiyi (olaylar) veya orkestrasyonu (komutlar) seçin.
- Çift yazma sorununu işlemsel dış kutu ve bir aktarıcıyla çözün.
- Bir gelen kutusu/tekilleştirme anahtarı kullanarak her tüketiciyi eşgüçlü hâle getirin.
- Dağıtık geri alma işlemleri için telafi edici eylemler içeren iş akışları kullanın.
- Olayları eklemeli biçimde sürümleyin ve izlenebilirlik için bir ilişkilendirme kimliği iletin.
Bu örüntüler, başıboş iletileri güvenilir ve gözlemlenebilir iş süreçlerine dönüştürür.
Sıkça Sorulan Sorular
“Olay Odaklı İş Akışları Oluşturma” dersi ücretsiz mi?
Evet — “Olay Odaklı İş Akışları Oluşturma” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve PHP Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. PHP Academy kursu toplamda 4 dersten oluşur.
“Olay Odaklı İş Akışları Oluşturma” dersinde ne öğreneceğim?
Hizmetleri olaylar ve idempotentlik aracılığıyla koordine edin. PHP Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
PHP Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te PHP Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Olay Odaklı İş Akışları Oluşturma” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu PHP Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her PHP Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Eşzamansız Mesajlaşma Neden Önemlidir
- PHP'te RabbitMQ ile Çalışma
- PHP ile Apache Kafka
- Olay Odaklı İş Akışları Oluşturma