0Pricing
PHP Academy · Lektion

Warum asynchrone Nachrichtenübermittlung

Sehen Sie, wie Queues Produzenten und Konsumenten entkoppeln.

Warum asynchrone Nachrichtenübermittlung ist eine kostenlose PHP Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des PHP Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum asynchrone Nachrichtenübermittlung

Bei einer synchronen Anfrage blockiert Ihr PHP-Prozess, während er mit E-Mail-Gateways, Zahlungsdienstleistern oder nachgelagerten Diensten kommuniziert. Unter Last koppelt dies Ihre Latenz und Verfügbarkeit an jede aufgerufene Abhängigkeit. Asynchrone Nachrichtenübermittlung durchbricht diese Kette: Der Produzent legt eine Nachricht in eine Queue und kehrt sofort zurück; die Konsumenten verarbeiten sie später in ihrem eigenen Tempo.

Diese Lektion behandelt das Warum – Entkopplung, Pufferung und die Abwägungen bei Zustellgarantien, die Sie verstehen müssen, bevor Sie RabbitMQ oder Kafka einsetzen.

Zeitliche und räumliche Entkopplung

Eine Queue entkoppelt Produzenten und Konsumenten entlang zweier Achsen:

  • Räumlich – keine der beiden Seiten benötigt die Adresse der anderen; beide kennen nur den Broker.
  • Zeitlich – der Konsument kann beim Veröffentlichen durch den Produzenten nicht verfügbar sein; die Nachricht wartet.

Die folgende synchrone Variante koppelt die Webanfrage an die Verfügbarkeit und Geschwindigkeit des Mailservers.

<?php
// Synchronous: the HTTP request blocks on SMTP
function registerUser(string $email): void {
    saveUser($email);
    // If SMTP is slow or down, the user waits or the request fails
    sendWelcomeEmail($email); // 800ms blocking call
    echo "Registered\n";
}

function saveUser(string $e): void { /* ... */ }
function sendWelcomeEmail(string $e): void { usleep(1); }

registerUser('dev@example.com');

Publizieren und weitermachen

Die asynchrone Variante speichert den Benutzer, veröffentlicht eine UserRegistered-Nachricht und kehrt zurück. Ein separater Worker versendet die E-Mail. Die HTTP-Latenz hängt nun nur noch vom schnellen Veröffentlichen beim lokalen Broker ab, nicht mehr vom SMTP-Roundtrip.

<?php
function registerUser(string $email): void {
    saveUser($email);
    // Publish a lightweight event; worker handles email later
    publish('user.registered', json_encode(['email' => $email]));
    echo "Registered (email queued)\n";
}

function saveUser(string $e): void { /* ... */ }
function publish(string $routingKey, string $payload): void {
    echo "-> queued $routingKey: $payload\n";
}

registerUser('dev@example.com');

Lastnivellierung (Pufferung)

Verkehrsspitzen sind ungleichmäßig; die Verarbeitungskapazität ist festgelegt. Eine Queue dient als Puffer: Sie nimmt eine Spitze von 10.000 Nachrichten auf und ermöglicht es einem Pool von Workern, diese mit einer nachhaltigen Rate abzuarbeiten. Ohne Queue würde die Spitze die Datenbank oder die nachgelagerte API direkt überlasten.

Das ist Lastnivellierung – Sie tauschen Latenz (Nachrichten können kurz warten) gegen Stabilität (nichts fällt aus).

Zustellgarantien

Jedes Nachrichtensystem gibt ein Zustellversprechen. Sie müssen wissen, welches für Sie gilt:

  • Höchstens einmal – auslösen und vergessen; Nachrichten können verloren gehen, werden aber nie dupliziert.
  • Mindestens einmal – erneute Zustellung bis zur Bestätigung; Duplikate sind möglich. Dies ist der übliche Standard.
  • Genau einmal – kein Verlust, keine Duplikate; teuer und auf Anwendungsebene oft nur eine teilweise Illusion.

Da die meisten realen Systeme Ihnen mindestens einmal bieten, müssen Ihre Konsumenten damit umgehen können, dieselbe Nachricht zweimal zu sehen.

Idempotente Konsumenten

Das Mittel gegen Duplikate bei mindestens einmaliger Zustellung ist Idempotenz: Die zweimalige Verarbeitung einer Nachricht führt zum selben Ergebnis wie die einmalige Verarbeitung. Üblicherweise wird dazu ein Deduplizierungsschlüssel (die Nachrichten-ID) in einem eindeutigen Index gespeichert.

<?php
function handle(array $msg, PDO $pdo): void {
    $pdo->beginTransaction();
    try {
        // Unique constraint on message_id makes the insert the dedup gate
        $stmt = $pdo->prepare(
            'INSERT INTO processed_messages (id) VALUES (?)'
        );
        $stmt->execute([$msg['id']]);
    } catch (PDOException $e) {
        $pdo->rollBack();
        echo "Duplicate {$msg['id']} skipped\n";
        return; // already handled
    }
    chargeCustomer($msg['amount']);
    $pdo->commit();
}
function chargeCustomer(int $a): void {}

Bestätigungen und erneute Zustellung

Ein Konsument signalisiert den Erfolg mit einer ack-Bestätigung. Wenn er vor dem Senden der Bestätigung abstürzt, stellt der Broker die Nachricht einem anderen Konsumenten erneut zu. Das ermöglicht die mindestens einmalige Zustellung – aber deshalb muss ein ack nachdem der Seiteneffekt festgeschrieben wurde erfolgen, niemals davor.

Bestätigen Sie zu früh und ein Absturz lässt die Nachricht verloren gehen. Bestätigen Sie zu spät (und stürzt der Prozess ab), erhalten Sie ein Duplikat – das Ihre Idempotenzschicht abfängt.

<?php
// Pseudocode of the consumer contract
function consumeLoop($channel): void {
    while ($msg = $channel->get()) {
        try {
            processSideEffect($msg);   // commit DB write first
            $channel->ack($msg);       // only then ack
        } catch (\Throwable $e) {
            $channel->nack($msg, requeue: true); // let it redeliver
        }
    }
}
function processSideEffect($m): void {}

Reihenfolge gibt es nicht umsonst

Queues garantieren keine globale Reihenfolge mehr, sobald Sie auf mehrere Konsumenten skalieren. Zwei Worker, die Nachrichten aus derselben Queue abrufen, verarbeiten sie nebenläufig, sodass Nachricht B vor Nachricht A abgeschlossen sein kann.

Wenn die Reihenfolge wichtig ist (z. B. bei Änderungen eines Kontostands), müssen Sie nach Schlüssel partitionieren, damit alle zusammengehörigen Nachrichten nacheinander an einen einzigen Konsumenten gehen. Kafka erledigt dies mit Partitionen nativ; bei RabbitMQ leiten Sie Nachrichten mithilfe eines konsistenten Hashes an Schlüssel-spezifische Queues weiter.

Dead-Letter-Queues

Einige Nachrichten können niemals erfolgreich verarbeitet werden – etwa wegen fehlerhafter Nutzdaten oder Verweisen auf gelöschte Datensätze. Werden sie unendlich oft erneut versucht, blockieren sie die Queue (eine Poison Message). Das entsprechende Muster ist eine Dead-Letter-Queue (DLQ): Nach N fehlgeschlagenen Versuchen wird die Nachricht zur Untersuchung beiseitegelegt, statt sie erneut zuzustellen.

<?php
function consume(array $msg, $channel): void {
    $attempts = ($msg['headers']['x-attempt'] ?? 0) + 1;
    try {
        process($msg);
        $channel->ack($msg);
    } catch (\Throwable $e) {
        if ($attempts >= 5) {
            $channel->deadLetter($msg); // park in DLQ
        } else {
            $channel->republish($msg, ['x-attempt' => $attempts]);
        }
    }
}
function process(array $m): void {}

Wann Sie KEINE Queue verwenden sollten

Asynchrone Nachrichtenübermittlung verursacht echte Betriebskosten: Sie benötigen einen zu betreibenden Broker, müssen dem Produktteam letztendliche Konsistenz erklären und über Prozessgrenzen hinweg schwieriger debuggen.

Greifen Sie zu einer Queue, wenn die Arbeit langsam, spiky, wiederholbar oder Fire-and-Forget ist. Bleiben Sie synchron, wenn der Aufrufer das Ergebnis wirklich jetzt benötigt (z. B. einen verbindlichen Preis, den der Benutzer sehen muss) – eine Verarbeitung über eine Queue zu verpacken, obwohl das Ergebnis benötigt wird, fügt lediglich Latenz und Komplexität hinzu.

Queue vs. Log

Zwei grundlegende Brokerformen unterstützen diese Muster, und der restliche Kurs verwendet beide:

  • Eine Task-Queue (RabbitMQ) löscht eine Nachricht, sobald sie bestätigt wurde. Sie eignet sich hervorragend, um Arbeit auf einen Pool konkurrierender Konsumenten zu verteilen, mit Routing pro Nachricht und TTLs.
  • Ein Commit-Log (Kafka) bewahrt Nachrichten entsprechend der Aufbewahrungsrichtlinie auf; jeder Konsument verfolgt seinen eigenen Offset und kann die Historie erneut abspielen, während viele unabhängige Konsumentengruppen denselben Stream lesen.

Wählen Sie die Queue für die Arbeitsverteilung und das Log für Event-Streams mit hohem Durchsatz und deren Wiederholung.

<?php
$useCase = 'replay events for a new analytics service';
$broker = str_contains($useCase, 'replay') || str_contains($useCase, 'stream')
    ? 'Kafka (commit log)'
    : 'RabbitMQ (task queue)';
echo $broker . "\n";

Schnelltest

Über Zustellgarantien nachdenken.

Zusammenfassung

Sie verfügen nun über das gedankliche Modell hinter der asynchronen Nachrichtenübermittlung:

  • Queues sorgen für räumliche und zeitliche Entkopplung und dienen als Puffer zur Lastnivellierung.
  • Die meisten Systeme liefern mindestens einmal, daher müssen Konsumenten idempotent sein.
  • Bestätigen Sie nach dem Commit des Seiteneffekts; lassen Sie Fehler eine erneute Zustellung auslösen.
  • Die Reihenfolge erfordert eine Partitionierung nach Schlüssel; Poison Messages benötigen eine DLQ.
  • Stellen Sie keine Arbeit in eine Queue, deren Ergebnis der Aufrufer synchron benötigt.

Als Nächstes setzen Sie dies mit RabbitMQ in PHP praktisch um.

Häufig gestellte Fragen

Ist die Lektion „Warum asynchrone Nachrichtenübermittlung“ kostenlos?

Ja — der vollständige Text von „Warum asynchrone Nachrichtenübermittlung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des PHP Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Warum asynchrone Nachrichtenübermittlung“?

Sehen Sie, wie Queues Produzenten und Konsumenten entkoppeln. Du übst PHP Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um PHP Academy zu starten?

Keine Vorkenntnisse erforderlich. PHP Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Warum asynchrone Nachrichtenübermittlung“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser PHP Academy-Lektion Code schreiben und ausführen?

Ja. Jede PHP Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum asynchrone Nachrichtenübermittlung
  2. Mit RabbitMQ in PHP arbeiten
  3. Apache Kafka mit PHP
  4. Ereignisgesteuerte Workflows erstellen
← Zurück zu PHP Academy