Signatur
Beschreibung
ZMQContext ist die grundlegende Klasse der ZMQ-PECL-Erweiterung und bildet den Einstiegspunkt für jede ZeroMQ-Kommunikation in PHP. Ein Kontext verwaltet intern einen Thread-Pool für asynchrone I/O-Operationen und stellt die Basis dar, auf der ZMQSocket-Instanzen erzeugt werden.
In der Regel wird pro Prozess genau ein einziger ZMQContext erzeugt und für alle zugehörigen Sockets wiederverwendet. Das Erstellen mehrerer Kontexte ist möglich, aber selten notwendig und erhöht den Ressourcenverbrauch. Der Kontext ist thread-sicher — Sockets hingegen dürfen nicht zwischen Threads geteilt werden.
Über den optionalen Parameter io_threads lässt sich die Anzahl der I/O-Threads steuern. Der Standardwert 1 ist für die meisten Anwendungsfälle ausreichend. Nur bei sehr hohem Nachrichtenaufkommen über viele Sockets ist eine Erhöhung sinnvoll. Mit dem Parameter is_persistent kann der Kontext über mehrere PHP-Requests hinweg persistent gehalten werden.
Typische Einsatzgebiete sind Message-Queuing, Publish/Subscribe-Muster, Request/Reply-Architekturen und allgemein verteilte Systeme, bei denen PHP als Producer, Consumer oder Broker agiert.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $io_threads | int | 1 | Anzahl der I/O-Threads, die der Kontext intern für asynchrone Operationen verwendet. Für die meisten Anwendungen ist der Standardwert 1 ausreichend. |
| $is_persistent | bool | true | Gibt an, ob der Kontext über mehrere PHP-Requests hinweg persistent gehalten werden soll. Bei true wird der Kontext im persistenten Speicher abgelegt und bei nachfolgenden Requests wiederverwendet. |
Beispiele
Einfacher Request/Reply-Server mit ZMQContext
<?php
// Einen ZMQ-Kontext mit 1 I/O-Thread erstellen
$context = new ZMQContext(1);
// Einen REP-Socket erstellen und an einen Port binden
$responder = new ZMQSocket($context, ZMQ::SOCKET_REP);
$responder->bind('tcp://*:5555');
echo "Server wartet auf Verbindungen..." . PHP_EOL;
while (true) {
// Nachricht empfangen
$message = $responder->recv();
echo "Empfangen: " . $message . PHP_EOL;
// Antwort senden
$responder->send('Antwort auf: ' . $message);
}
Publish/Subscribe-Publisher mit persistentem Kontext
<?php
// Persistenter Kontext: wird über mehrere Requests wiederverwendet
$context = new ZMQContext(1, true);
// PUB-Socket erstellen
$publisher = new ZMQSocket($context, ZMQ::SOCKET_PUB);
$publisher->bind('tcp://*:5556');
// Kurz warten, damit sich Subscriber verbinden können
usleep(100000);
// Nachrichten an alle Subscriber senden
for ($i = 1; $i <= 5; $i++) {
$publisher->send('Nachricht Nr. ' . $i);
echo 'Gesendet: Nachricht Nr. ' . $i . PHP_EOL;
usleep(500000);
}
Kontext-Optionen lesen und setzen
<?php
$context = new ZMQContext();
// Anzahl der I/O-Threads abfragen
$threads = $context->getOpt(ZMQ::CTXOPT_IO_THREADS);
echo 'I/O-Threads: ' . $threads . PHP_EOL;
// Maximale Anzahl der Sockets setzen
$context->setOpt(ZMQ::CTXOPT_MAX_SOCKETS, 1024);
$maxSockets = $context->getOpt(ZMQ::CTXOPT_MAX_SOCKETS);
echo 'Maximale Sockets: ' . $maxSockets . PHP_EOL;
// Wichtig · Fallstricke
Ressourcenverwaltung: Ein ZMQContext sollte erst dann zerstört werden (oder den Gültigkeitsbereich verlassen), wenn alle zugehörigen Sockets geschlossen wurden. Andernfalls kann es zu hängendem Verhalten kommen, da ZeroMQ intern darauf wartet, alle ausstehenden Nachrichten zuzustellen (Linger-Verhalten).
Persistenz: Bei is_persistent = true (Standard) wird der Kontext im persistenten PHP-Speicher gehalten. Das bedeutet, dass er nicht bei jedem Request neu erzeugt wird, aber auch nicht explizit durch PHP-Code zerstört werden kann. Dies ist für langlebige Prozesse wie PHP-CLI-Skripte oder PHP-FPM-Worker vorteilhaft.
Thread-Sicherheit: ZMQContext ist thread-sicher, ZMQSocket-Instanzen jedoch nicht. Sockets dürfen niemals zwischen Threads geteilt werden — jeder Thread sollte eigene Sockets aus einem gemeinsamen Kontext erzeugen.
Erweiterung erforderlich: ZMQContext ist Teil der PECL-Erweiterung zmq, die separat installiert werden muss (pecl install zmq). Die zugrundeliegende C-Bibliothek libzmq muss ebenfalls vorhanden sein.