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
$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
$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
$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_MIBmierzy 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: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
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
$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/statmna 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 $workerrzuca\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()to0,startTime()to czas startu procesu,requestCount()to0,rss()to bieżący RSS, aserve()rzucaInvalidServeContextException.
Zobacz też
- Tryb worker — omówienie trwałych procesów PHP oraz wzorca bootstrap-once
- Funkcje PHP — dokumentacja starszych wolnych funkcji
oxphp_* - Request API —
OxPHP\Http\RequestInterface::startTime()do pomiaru czasu per-żądanie