Start · Sprachen · PHP · Referenz · Swoole\Channel

Swoole\Channel

Klasse

Repräsentiert einen prozessübergreifenden Kommunikationskanal auf Basis von Shared Memory für schnelle Inter-Prozess-Kommunikation.

seit PHP 1.9.0 Kategorie: misc

Signatur

class Swoole\Channel

Beschreibung

Swoole\Channel implementiert einen blockierenden FIFO-Puffer im gemeinsam genutzten Speicher (Shared Memory), über den mehrere Prozesse Nachrichten austauschen können. Er eignet sich besonders für Szenarien, in denen Swoole\Process-Kinder-Prozesse Daten an einen Master-Prozess senden oder umgekehrt, ohne auf Sockets oder Pipes angewiesen zu sein.

Der Kanal funktioniert nach dem Producer-Consumer-Prinzip: Ein Prozess schreibt Daten mit push() in den Puffer, ein anderer liest sie mit pop() heraus. Da der Kanal auf Shared Memory basiert, ist er deutlich schneller als Pipe- oder Socket-basierte IPC-Mechanismen, hat jedoch eine feste maximale Kapazität, die beim Erstellen festgelegt wird.

Ein wichtiger Unterschied zu Swoole\Table ist, dass Swoole\Channel als Warteschlange (Queue) konzipiert ist: Daten werden sequentiell gelesen und dabei aus dem Puffer entfernt. Komplexe PHP-Strukturen wie Arrays und Objekte werden dabei automatisch serialisiert.

Der Kanal muss vor dem Erstellen der Kind-Prozesse instanziiert werden, damit alle beteiligten Prozesse Zugriff auf denselben Shared-Memory-Bereich haben. Er ist nicht für den Einsatz in Coroutine-Kontexten gedacht – für Coroutines sollte stattdessen Swoole\Coroutine\Channel verwendet werden.

Parameter

Name Typ Default Beschreibung
$size Pflicht int Größe des Shared-Memory-Puffers in Bytes. Dieser Wert legt die maximale Kapazität des Kanals fest und kann nach der Erstellung nicht mehr verändert werden. Empfohlen werden Vielfache von 4096.

Rückgabewert

Typ

Beispiele

Einfache prozessübergreifende Kommunikation mit push/pop

<?php
// Kanal mit 64 KB Puffer erstellen (vor fork!)
$channel = new Swoole\Channel(1024 * 64);

$pid = pcntl_fork();
if ($pid === 0) {
    // Kind-Prozess: Daten in den Kanal schreiben
    $data = ['message' => 'Hallo vom Kind-Prozess', 'timestamp' => time()];
    $channel->push($data);
    echo "Kind: Daten gesendet.\n";
    exit(0);
} else {
    // Master-Prozess: kurz warten, dann Daten lesen
    sleep(1);
    $received = $channel->pop();
    echo "Master empfangen: " . $received['message'] . "\n";
    pcntl_wait($status);
}
Kind: Daten gesendet. Master empfangen: Hallo vom Kind-Prozess

Verwendung mit Swoole\Process für Worker-Pool

<?php
// Kanal mit 256 KB Puffer
$channel = new Swoole\Channel(1024 * 256);

$workers = [];
for ($i = 0; $i < 3; $i++) {
    $process = new Swoole\Process(function (Swoole\Process $worker) use ($channel, $i) {
        // Jeder Worker schreibt eine Aufgabe in den Kanal
        $task = "Ergebnis von Worker #{$i}: " . rand(100, 999);
        $channel->push($task);
        echo "Worker #{$i} hat Daten gesendet.\n";
    });
    $process->start();
    $workers[] = $process;
}

// Auf alle Worker warten
foreach ($workers as $worker) {
    Swoole\Process::wait();
}

// Alle Ergebnisse aus dem Kanal lesen
for ($i = 0; $i < 3; $i++) {
    $result = $channel->pop();
    echo "Gelesen: {$result}\n";
}
Worker #0 hat Daten gesendet. Worker #1 hat Daten gesendet. Worker #2 hat Daten gesendet. Gelesen: Ergebnis von Worker #0: 742 Gelesen: Ergebnis von Worker #1: 315 Gelesen: Ergebnis von Worker #2: 891

// Wichtig · Fallstricke

Wichtige Hinweise:

  • Der Kanal muss zwingend vor dem Aufruf von pcntl_fork() oder Swoole\Process::start() erstellt werden, damit alle Prozesse denselben Shared-Memory-Bereich nutzen.
  • Wenn der Puffer voll ist, blockiert push() so lange, bis ein anderer Prozess Daten mit pop() entnimmt. Achte darauf, Deadlocks zu vermeiden.
  • pop() blockiert, wenn der Kanal leer ist, bis neue Daten verfügbar sind. Dies kann in bestimmten Szenarien zu Hängeern führen.
  • Für den Einsatz in Coroutines ist Swoole\Coroutine\Channel zu bevorzugen, da Swoole\Channel nicht coroutine-aware ist und den Event Loop blockieren kann.
  • PHP-Arrays und Objekte werden intern automatisch serialisiert/deserialisiert, was bei sehr großen Datenstrukturen zu Performance-Einbußen führen kann.
  • Der maximale Puffer ist durch den beim Erstellen angegebenen size-Wert begrenzt. Eine einzelne Nachricht darf diese Größe nicht überschreiten.