Клас Worker

OxPHP\Server\Worker — це єдиний дескриптор середовища виконання для всього, що повʼязано з одним робочим потоком ОС в OxPHP. Це фінальна обгортка без власного стану над потоково-локальним станом bridge; її реєструє саме розширення SAPI, тому вона завжди доступна як у традиційному режимі, так і в режимі воркерів. Кожен виклик читає актуальний стан безпосередньо із середовища виконання; сам обʼєкт нічого не кешує.

Worker::current() повертає синглтон для кожного потоку ОС: два виклики в одному потоці завжди повертають той самий екземпляр.

Короткий довідник

Метод Опис
Worker::current(): self Повертає дескриптор-синглтон для поточного потоку ОС.
Worker::isWorkerMode(): bool Повертає true, якщо сервер працює в режимі воркерів (тобто WORKER_MODE_ENABLED=true).
id(): int Числовий ідентифікатор воркера в діапазоні 0..N-1 для поточного потоку ОС.
startTime(): float Unix-мітка часу (у секундах), коли було запущено цей робочий потік ОС.
requestCount(): int Лічильник запитів, оброблених цим потоком ОС, починаючи з 1. Зростає в обох режимах.
memoryUsage(): int Поточне використання памʼяті PHP у байтах (zend_memory_usage(0)).
rss(): int Резидентний розмір процесу (RSS) у байтах. Не кешується — викликайте не частіше ніж раз на запит.
maxMemoryBytes(): int Налаштований ліміт памʼяті в байтах. 0 означає «без обмежень».
scheduleExit(): void Позначає воркер для коректного завершення після того, як поточний запит буде оброблено. У традиційному режимі нічого не робить.
isExitScheduled(): bool Повертає true, щойно для поточного воркера заплановано завершення з причиною 'scheduled': було викликано scheduleExit() або воркер сам ініціював своє завершення. Завершення 'max_memory' і 'error' його не встановлюють. У традиційному режимі завжди false.
exitReason(): ?string Причина очікуваного завершення: 'scheduled' (було викликано scheduleExit() або воркер сам ініціював своє завершення: після фатальної помилки, після якої він не може повністю відновитися, або тому, що запит, завершений із викликом внутрішньої функції на стеку, лишив його з набагато більшим обсягом памʼяті), 'max_memory', 'error' або null, якщо завершення не заплановано. У традиційному режимі завжди null.
serve(callable $h): void Входить у цикл обробки запитів. Поза режимом воркерів кидає InvalidServeContextException.

Поведінка в різних режимах

Метод Традиційний режим Режим воркерів
current() Синглтон на потік ОС. Синглтон на потік ОС.
isWorkerMode() false true
id() Індекс потоку ОС у пулі воркерів. Індекс потоку ОС у пулі воркерів.
startTime() Час запуску потоку ОС (зазвичай — старт сервера). Час запуску потоку ОС.
requestCount() Починається з 1 і зростає з кожним запитом, що повторно використовує той самий потік ОС (1, 2, 3, …). Починається з 1 і зростає з кожним запитом, обробленим воркером.
memoryUsage() Поточна памʼять PHP на момент виклику. Поточна памʼять PHP на момент виклику.
rss() Поточний RSS процесу. Поточний RSS процесу.
maxMemoryBytes() 0 (ліміт для перезапуску не застосовується). Значення WORKER_MAX_MEMORY_MIB × 1 MiB або 0, якщо не задано.
scheduleExit() Нічого не робить (скрипт і так завершується). Встановлює прапорець завершення; цикл обробки запитів зупиняється після повернення поточного обробника.
isExitScheduled() Завжди false. true після виклику scheduleExit() у цьому потоці або після того, як воркер сам ініціював своє завершення. Завершення 'max_memory' і 'error' його не встановлюють.
exitReason() Завжди null. null, доки завершення не заплановано; потім одне з 'scheduled', 'max_memory', 'error'.
serve(callable) Кидає OxPHP\Server\Exception\InvalidServeContextException. Входить у цикл обробки запитів.

Приклади

Контекст логування для кожного воркера

Додавайте до кожного рядка логу ідентифікатор воркера та лічильник запитів потоку, щоб співвідносити трафік запитів із конкретним воркером.

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

Одноразова ініціалізація в кожному потоці ОС

requestCount() починається з 1, тож перший запит, який обробляє будь-який потік, бачить значення 1. Це переносиме місце для лінивої ініціалізації на рівні потоку, яка має виконатися рівно один раз.

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

scheduleExit

Перезапуск воркерів з ініціативи застосунку. Поточний запит завершується як зазвичай; після цього цикл перевіряє isExitScheduled() і виходить. Супервізор запускає на його місці новий воркер, заново виконуючи зовнішню область видимості файлу воркера. Статичний пул робить це під час наступного сканування; динамічний — лише тоді, коли розмір пулу дорівнює мінімальному або менший за нього. Див. Перезапуск.

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

scheduleExit() ідемпотентний і поза режимом воркерів нічого не робить. Сценарії використання:

  • Гаряче перезавантаження під час розробки. Завершуйте воркер після кожного запиту, щоб ініціалізація у зовнішній області видимості виконувалася знову.

  • Перезапуск за RSS. WORKER_MAX_MEMORY_MIB враховує лише алокатор Zend. Якщо стек активно використовує розширення (curl, mysqli), можна додатково перезапускати воркер, коли RSS процесу перевищує ваш власний поріг:

    php
    if ($worker->rss() > 256 * 1024 * 1024) { $worker->scheduleExit(); }
  • Узгоджені поетапні перезапуски. Обумовте виклик наявністю файлу-маркера або сигналом, щоб зовнішній оркестратор міг акуратно звільняти воркери.

Точка входу воркера

У скрипті ініціалізації воркера викличте serve(), щоб увійти в цикл обробки запитів.

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

Спостереження за RSS

rss() повертає поточний резидентний розмір процесу в байтах. Виклик — це справжній системний виклик: дешевий, але не безкоштовний. Читайте це значення не частіше ніж раз на запит.

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

Перехід із функцій oxphp_*

Застарілі вільні функції залишаються доступними й працюють через той самий внутрішній стан. Вони не оголошені застарілими (deprecated). У новому коді краще використовувати API класу — його легше знайти, і він послідовніший.

Застаріла функція API класу
oxphp_is_worker() OxPHP\Server\Worker::isWorkerMode()
oxphp_worker_id() OxPHP\Server\Worker::current()->id()
oxphp_worker(callable) OxPHP\Server\Worker::current()->serve(callable)

Застереження

  • rss() не кешується. Кожен виклик виконує системний виклик (читання /proc/self/statm у Linux, getrusage(RUSAGE_SELF) у macOS). Це дешево, але не безкоштовно, тож викликайте його не частіше ніж раз на запит — зазвичай в обробнику метрик, а не в кожному рядку логу.
  • Клонування заборонено. clone $worker кидає \Error("Cloning OxPHP\\Server\\Worker is not allowed"). Дескриптор воркера представляє ідентичність потоку ОС; клонування створило б оманливе враження, ніби для того самого потоку існує другий дескриптор.
  • Поза хостом OxPHP (наприклад, коли розширення, що лінкує SAPI, завантажено в PHP CLI) Worker::current() усе одно повертає екземпляр, але кожен метод доступу повертає своє нульове значення: id() дорівнює 0, startTime() — час запуску процесу, requestCount() дорівнює 0, rss() — поточний RSS, а serve() кидає InvalidServeContextException.

Промпти для вашого агента

Ці промпти розраховані на агента з підключеним MCP-сервером документації OxPHP — потрібні сторінки він прочитає сам.

prompt
Додай до мого застосунку інспектування воркерів за допомогою `OxPHP\Server\Worker`. Прочитай сторінку `php/worker-class` через MCP-сервер документації OxPHP. Знайди місця, де мій код логує кожен запит або виконує одноразову ініціалізацію, і підключи `Worker::current()->id()` та `requestCount()` до рядків логу, а для ініціалізації — перевірку `requestCount() === 1`.

Див. також

  • Режим воркерів — огляд постійних PHP-воркерів і патерну одноразової ініціалізації
  • Функції PHP — довідка із застарілих вільних функцій oxphp_*
  • API запиту — OxPHP\Http\RequestInterface::startTime() для вимірювання часу кожного запиту