Classe Worker

OxPHP\Server\Worker est le handle d'exécution unifié pour tout ce qui est lié à un seul thread worker OS d'OxPHP. C'est un wrapper final et sans état par-dessus l'état thread-local du bridge, enregistré par l'extension SAPI elle-même, si bien qu'il est toujours disponible aussi bien en mode traditionnel qu'en mode worker. Chaque appel lit l'état vivant directement depuis le runtime ; l'objet lui-même ne met rien en cache.

Worker::current() renvoie un singleton par thread OS : deux appels sur le même thread renvoient toujours la même instance.

Référence rapide

Méthode Description
Worker::current(): self Renvoie le handle singleton pour le thread OS courant.
Worker::isWorkerMode(): bool Renvoie true si le serveur tourne en mode worker (c.-à-d. WORKER_MODE_ENABLED=true).
id(): int Identifiant numérique du worker dans la plage 0..N-1 pour le thread OS courant.
startTime(): float Timestamp Unix (en secondes) du moment où ce thread worker OS a été lancé.
requestCount(): int Nombre de requêtes traitées par ce thread OS (compté à partir de 1). Augmente dans les deux modes.
memoryUsage(): int Utilisation mémoire PHP vivante en octets (zend_memory_usage(0)).
rss(): int Taille de l'ensemble résident (RSS) du processus en octets. Non mis en cache — à appeler au plus une fois par requête.
maxMemoryBytes(): int Plafond mémoire configuré en octets. 0 signifie illimité.
scheduleExit(): void Marque le worker pour un arrêt gracieux après la fin de la requête courante. Sans effet en mode traditionnel.
isExitScheduled(): bool Renvoie true si scheduleExit() a été appelée pour le worker courant. Toujours false en mode traditionnel.
exitReason(): ?string Raison de l'arrêt en attente : 'scheduled', 'max_memory', 'error', ou null quand aucun arrêt n'est en attente. Toujours null en mode traditionnel.
serve(callable $h): void Entre dans la boucle de requêtes. Lève InvalidServeContextException en dehors du mode worker.

Matrice des modes

Méthode Mode traditionnel Mode worker
current() Singleton par thread OS. Singleton par thread OS.
isWorkerMode() false true
id() Index du thread OS dans le pool de workers. Index du thread OS dans le pool de workers.
startTime() Moment où le thread OS a été lancé (généralement le démarrage du serveur). Moment où le thread OS a été lancé.
requestCount() Compté à partir de 1, s'incrémente au fil des requêtes qui réutilisent le même thread OS (1, 2, 3, …). Compté à partir de 1, s'incrémente à chaque requête traitée par le worker.
memoryUsage() Mémoire PHP vivante au moment de l'appel. Mémoire PHP vivante au moment de l'appel.
rss() RSS vivant du processus. RSS vivant du processus.
maxMemoryBytes() 0 (aucun plafond de recyclage ne s'applique). Valeur de WORKER_MAX_MEMORY_MIB × 1 Mio, ou 0 si non défini.
scheduleExit() Sans effet (le script se termine de toute façon). Positionne le drapeau d'arrêt ; la boucle de requêtes s'arrête après le retour du handler courant.
isExitScheduled() Toujours false. true après que scheduleExit() a été appelée sur ce thread.
exitReason() Toujours null. null jusqu'à ce qu'un arrêt soit en attente ; ensuite l'une des valeurs 'scheduled', 'max_memory', 'error'.
serve(callable) Lève OxPHP\Server\Exception\InvalidServeContextException. Entre dans la boucle de requêtes.

Exemples

Contexte de journalisation par worker

Étiquetez chaque ligne de journal avec l'id du worker et le compteur de requêtes par thread, afin de pouvoir corréler le trafic de requêtes avec un worker donné.

php
<?php $worker = OxPHP\Server\Worker::current(); $logger->info('handling request', [ 'worker_id' => $worker->id(), 'request_number' => $worker->requestCount(), ]);

Bootstrap une seule fois par thread OS

requestCount() est compté à partir de 1, si bien que la première requête traitée par un thread quelconque voit la valeur 1. C'est un endroit portable pour exécuter une initialisation paresseuse par thread qui ne doit se produire qu'exactement une fois.

php
<?php $worker = OxPHP\Server\Worker::current(); if ($worker->requestCount() === 1) { bootstrap(); }

scheduleExit

Recyclage de worker piloté par l'application. La requête courante se termine normalement ; la boucle vérifie ensuite isExitScheduled() et en sort. Le superviseur relance un worker frais, ré-exécutant la portée externe du fichier worker.

php
<?php $worker = OxPHP\Server\Worker::current(); handleRequest(); // Reload bootstrap on every request when developing locally. if (getenv('OXPHP_DEV') === '1') { $worker->scheduleExit(); }

scheduleExit() est idempotente et sans effet en dehors du mode worker. Cas d'usage :

  • Rechargement à chaud pendant le développement. Sortir après chaque requête pour que le bootstrap de la portée externe soit ré-exécuté.

  • Recyclage basé sur le RSS. WORKER_MAX_MEMORY_MIB ne mesure que l'allocateur Zend. Avec des piles riches en extensions (curl, mysqli), vous pouvez en plus recycler quand le RSS du processus franchit votre propre seuil :

    php
    if ($worker->rss() > 256 * 1024 * 1024) { $worker->scheduleExit(); }
  • Redémarrages progressifs coordonnés. Conditionnez l'appel à un fichier sentinelle ou à un signal pour qu'un orchestrateur externe puisse drainer les workers proprement.

Point d'entrée du worker

Dans un script de bootstrap de worker, appelez serve() pour entrer dans la boucle de requêtes.

php
<?php require __DIR__ . '/../vendor/autoload.php'; OxPHP\Server\Worker::current()->serve(function () { handleRequest(); });

Observabilité du RSS

rss() renvoie la taille de l'ensemble résident (RSS) vivant du processus en octets. L'appel est un véritable appel système : peu coûteux, mais pas gratuit. Lisez-le au plus une fois par requête.

php
<?php $worker = OxPHP\Server\Worker::current(); $rss = $worker->rss(); $metrics->gauge('php_worker_rss_bytes', $rss, [ 'worker_id' => (string) $worker->id(), ]);

Migration depuis les fonctions oxphp_*

Les anciennes fonctions libres restent disponibles et passent par le même état interne. Elles ne sont pas dépréciées. Le nouveau code devrait privilégier l'API de classe pour la découvrabilité et la cohérence.

Fonction héritée API de classe
oxphp_is_worker() OxPHP\Server\Worker::isWorkerMode()
oxphp_worker_id() OxPHP\Server\Worker::current()->id()
oxphp_worker(callable) OxPHP\Server\Worker::current()->serve(callable)

Points d'attention

  • rss() n'est pas mis en cache. Chaque appel effectue un appel système (lecture de /proc/self/statm sous Linux, getrusage(RUSAGE_SELF) sous macOS). Peu coûteux mais pas gratuit, alors appelez-le au plus une fois par requête, typiquement dans un handler de métriques, et non sur chaque ligne de journal.
  • Le clonage est interdit. clone $worker lève \Error("Cloning OxPHP\\Server\\Worker is not allowed"). Le handle worker représente l'identité d'un thread OS ; le cloner donnerait l'impression trompeuse d'un second handle pour le même thread.
  • En dehors d'un hôte OxPHP (par exemple lorsqu'une extension liant le SAPI est chargée dans le PHP CLI), Worker::current() renvoie toujours une instance, mais chaque accesseur renvoie sa valeur d'état zéro : id() vaut 0, startTime() est le moment de démarrage du processus, requestCount() vaut 0, rss() est le RSS vivant, et serve() lève InvalidServeContextException.

Voir aussi

  • Mode worker — vue d'ensemble des processus PHP persistants et du motif « bootstrap une seule fois »
  • Fonctions PHP — référence des anciennes fonctions libres oxphp_*
  • API de requêteOxPHP\Http\RequestInterface::startTime() pour la mesure du temps par requête