Klasa Worker

OxPHP\Server\Worker to ujednolicony uchwyt runtime obejmujący wszystko, co jest związane z pojedynczym wątkiem workera systemu operacyjnego OxPHP. Jest to finalny, bezstanowy wrapper nad stanem thread-local mostka, rejestrowany przez samo rozszerzenie SAPI, dzięki czemu jest zawsze dostępny zarówno w trybie tradycyjnym, jak i w trybie worker. Każde wywołanie odczytuje stan na żywo bezpośrednio z runtime; sam obiekt niczego nie buforuje.

Worker::current() zwraca singleton dla każdego wątku OS: dwa wywołania na tym samym wątku zawsze zwracają tę samą instancję.

Szybka referencja

Metoda Opis
Worker::current(): self Zwraca uchwyt singletona dla bieżącego wątku OS.
Worker::isWorkerMode(): bool Zwraca true, jeśli serwer działa w trybie worker (czyli WORKER_MODE_ENABLED=true).
id(): int Numeryczny identyfikator workera z zakresu 0..N-1 dla bieżącego wątku OS.
startTime(): float Znacznik czasu Unix (w sekundach) utworzenia tego wątku workera OS.
requestCount(): int Liczba żądań obsłużonych przez ten wątek OS, liczona od 1. Rośnie w obu trybach.
memoryUsage(): int Bieżące zużycie pamięci PHP w bajtach (zend_memory_usage(0)).
rss(): int Rozmiar rezydentnego zbioru pamięci procesu (RSS) w bajtach. Bez buforowania — wywołuj najwyżej raz na żądanie.
maxMemoryBytes(): int Skonfigurowany limit pamięci w bajtach. 0 oznacza brak limitu.
scheduleExit(): void Oznacza workera do łagodnego zakończenia po ukończeniu bieżącego żądania. W trybie tradycyjnym nie robi nic.
isExitScheduled(): bool Zwraca true, jeśli dla bieżącego workera wywołano scheduleExit(). W trybie tradycyjnym zawsze false.
exitReason(): ?string Oczekujący powód zakończenia: 'scheduled', 'max_memory', 'error' lub null, gdy żadne zakończenie nie jest oczekujące. W trybie tradycyjnym zawsze null.
serve(callable $h): void Wchodzi w pętlę żądań. Poza trybem worker rzuca InvalidServeContextException.

Macierz trybów

Metoda Tryb tradycyjny Tryb worker
current() Singleton dla każdego wątku OS. Singleton dla każdego wątku OS.
isWorkerMode() false true
id() Indeks wątku OS w puli workerów. Indeks wątku OS w puli workerów.
startTime() Czas utworzenia wątku OS (zwykle start serwera). Czas utworzenia wątku OS.
requestCount() Liczone od 1, rośnie przy kolejnych żądaniach wykorzystujących ponownie ten sam wątek OS (1, 2, 3, …). Liczone od 1, rośnie z każdym żądaniem obsłużonym przez workera.
memoryUsage() Bieżąca pamięć PHP w momencie wywołania. Bieżąca pamięć PHP w momencie wywołania.
rss() Bieżący RSS procesu. Bieżący RSS procesu.
maxMemoryBytes() 0 (limit recyklingu nie obowiązuje). Wartość WORKER_MAX_MEMORY_MIB × 1 MiB lub 0, jeśli nie ustawiono.
scheduleExit() Nie robi nic (skrypt i tak kończy działanie). Ustawia flagę zakończenia; pętla żądań zatrzymuje się po powrocie bieżącego handlera.
isExitScheduled() Zawsze false. true po wywołaniu scheduleExit() na tym wątku.
exitReason() Zawsze null. null, dopóki żadne zakończenie nie jest oczekujące; potem jedna z wartości 'scheduled', 'max_memory', 'error'.
serve(callable) Rzuca OxPHP\Server\Exception\InvalidServeContextException. Wchodzi w pętlę żądań.

Przykłady

Kontekst logowania per-worker

Oznaczaj każdą linię logu identyfikatorem workera i licznikiem żądań per-wątek, aby móc powiązać ruch żądań z konkretnym workerem.

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

Bootstrap raz na wątek OS

requestCount() jest liczone od 1, więc pierwsze żądanie obsłużone przez dowolny wątek widzi wartość 1. To przenośne miejsce na uruchomienie leniwej inicjalizacji per-wątek, która powinna zajść dokładnie raz.

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

scheduleExit

Sterowany aplikacją recykling workerów. Bieżące żądanie kończy się normalnie; pętla następnie sprawdza isExitScheduled() i wychodzi. Nadzorca tworzy ponownie świeżego workera, ponownie wykonując zewnętrzny zakres pliku workera.

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

scheduleExit() jest idempotentne i poza trybem worker nie robi nic. Przypadki użycia:

  • Hot reload podczas rozwoju. Zakończ po każdym żądaniu, aby bootstrap w zewnętrznym zakresie wykonał się ponownie.

  • Recykling oparty na RSS. WORKER_MAX_MEMORY_MIB mierzy wyłącznie alokator Zend. Przy stosach mocno korzystających z rozszerzeń (curl, mysqli) możesz dodatkowo recyklingować, gdy RSS procesu przekroczy twój własny próg:

    php
    if ($worker->rss() > 256 * 1024 * 1024) { $worker->scheduleExit(); }
  • Skoordynowane restarty kroczące. Uzależnij wywołanie od pliku-wartownika lub sygnału, aby zewnętrzny orkiestrator mógł czysto opróżnić workery.

Punkt wejścia workera

W skrypcie bootstrap workera wywołaj serve(), aby wejść w pętlę żądań.

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

Obserwowalność RSS

rss() zwraca bieżący rozmiar rezydentnego zbioru pamięci procesu w bajtach. Wywołanie to prawdziwe wywołanie systemowe: tanie, ale nie darmowe. Odczytuj je najwyżej raz na żądanie.

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

Migracja z funkcji oxphp_*

Starsze wolne funkcje pozostają dostępne i korzystają z tego samego wewnętrznego stanu. Nie są przestarzałe. Nowy kod powinien preferować API klasy ze względu na odkrywalność i spójność.

Starsza funkcja API klasy
oxphp_is_worker() OxPHP\Server\Worker::isWorkerMode()
oxphp_worker_id() OxPHP\Server\Worker::current()->id()
oxphp_worker(callable) OxPHP\Server\Worker::current()->serve(callable)

Zastrzeżenia

  • rss() nie jest buforowane. Każde wywołanie wykonuje wywołanie systemowe (odczyt /proc/self/statm na Linuksie, getrusage(RUSAGE_SELF) na macOS). Tanie, ale nie darmowe, więc wywołuj je najwyżej raz na żądanie, zwykle wewnątrz handlera metryk, a nie w każdej linii logu.
  • Klonowanie jest zabronione. clone $worker rzuca \Error("Cloning OxPHP\\Server\\Worker is not allowed"). Uchwyt workera reprezentuje tożsamość wątku OS; jego klonowanie stworzyłoby mylące wrażenie istnienia drugiego uchwytu dla tego samego wątku.
  • Poza hostem OxPHP (np. gdy rozszerzenie linkujące SAPI zostanie załadowane do PHP CLI) Worker::current() nadal zwraca instancję, ale każdy akcesor zwraca wartość swojego stanu zerowego: id() to 0, startTime() to czas startu procesu, requestCount() to 0, rss() to bieżący RSS, a serve() rzuca InvalidServeContextException.

Zobacz też

  • Tryb worker — omówienie trwałych procesów PHP oraz wzorca bootstrap-once
  • Funkcje PHP — dokumentacja starszych wolnych funkcji oxphp_*
  • Request APIOxPHP\Http\RequestInterface::startTime() do pomiaru czasu per-żądanie