Worker クラス

OxPHP\Server\Worker は、単一の OxPHP OS ワーカースレッドに紐づくあらゆるものを扱う、統一されたランタイムハンドルです。これはブリッジのスレッドローカル状態をラップする final かつステートレスなラッパーであり、SAPI 拡張自体によって登録されるため、従来モードとワーカーモードの両方で常に利用できます。各呼び出しはランタイムから直接ライブの状態を読み取り、オブジェクト自体は何もキャッシュしません。

Worker::current() は OS スレッドごとにシングルトンを返します。同じスレッド上での 2 回の呼び出しは、常に同じインスタンスを返します。

クイックリファレンス

メソッド 説明
Worker::current(): self 現在の OS スレッドのシングルトンハンドルを返します。
Worker::isWorkerMode(): bool サーバーがワーカーモードで動作している場合(つまり WORKER_MODE_ENABLED=true の場合)に true を返します。
id(): int 現在の OS スレッドに対する 0..N-1 の範囲の数値ワーカー識別子です。
startTime(): float この OS ワーカースレッドが起動された時刻の Unix タイムスタンプ(秒)です。
requestCount(): int この OS スレッドが処理したリクエストの 1 始まりのカウントです。両モードで増加します。
memoryUsage(): int 現在の PHP メモリ使用量(バイト単位、zend_memory_usage(0))です。
rss(): int プロセスの resident set size(バイト単位)です。キャッシュされません。リクエストごとに最大 1 回だけ呼び出してください。
maxMemoryBytes(): int 設定されたメモリ上限(バイト単位)です。0 は無制限を意味します。
scheduleExit(): void 現在のリクエスト完了後にワーカーをグレースフルに終了するようマークします。従来モードでは何もしません。
isExitScheduled(): bool 現在のワーカーに対して scheduleExit() が呼び出されている場合に true を返します。従来モードでは常に false です。
exitReason(): ?string 保留中の終了理由です。'scheduled''max_memory''error'、または終了が保留されていない場合は null です。従来モードでは常に null です。
serve(callable $h): void リクエストループに入ります。ワーカーモード外では InvalidServeContextException をスローします。

モードマトリクス

メソッド 従来モード ワーカーモード
current() OS スレッドごとのシングルトン。 OS スレッドごとのシングルトン。
isWorkerMode() false true
id() ワーカープール内の OS スレッドのインデックス。 ワーカープール内の OS スレッドのインデックス。
startTime() OS スレッドが起動された時刻(通常はサーバー起動時)。 OS スレッドが起動された時刻。
requestCount() 1 始まりで、同じ OS スレッドを再利用するリクエストをまたいで増加します(1, 2, 3, …)。 1 始まりで、ワーカーが処理するリクエストごとに増加します。
memoryUsage() 呼び出し時点のライブの PHP メモリ。 呼び出し時点のライブの PHP メモリ。
rss() プロセスのライブ RSS。 プロセスのライブ RSS。
maxMemoryBytes() 0(リサイクル上限は適用されません)。 WORKER_MAX_MEMORY_MIB × 1 MiB の値、未設定の場合は 0
scheduleExit() 何もしません(どのみちスクリプトは終了します)。 終了フラグを設定します。現在のハンドラーが返った後にリクエストループが停止します。
isExitScheduled() 常に false このスレッドで scheduleExit() が呼び出された後は true
exitReason() 常に null 終了が保留されるまでは null。その後は 'scheduled''max_memory''error' のいずれか。
serve(callable) OxPHP\Server\Exception\InvalidServeContextException をスローします。 リクエストループに入ります。

ワーカーごとのロギングコンテキスト

すべてのログ行にワーカー ID とスレッドごとのリクエストカウンターを付与することで、リクエストトラフィックを特定のワーカーに関連付けられます。

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

OS スレッドごとに一度だけブートストラップする

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() はプロセスの現在の resident set size をバイト単位で返します。この呼び出しは実際のシステムコールであり、低コストですが無料ではありません。リクエストごとに最大 1 回だけ読み取ってください。

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

oxphp_* 関数からの移行

レガシーのフリー関数は引き続き利用可能で、同じ内部状態を経由します。これらは非推奨ではありません。新しいコードでは、発見しやすさと一貫性のためにクラス 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() はキャッシュされません。 各呼び出しはシステムコール(Linux では /proc/self/statm の読み取り、macOS では getrusage(RUSAGE_SELF))を実行します。低コストですが無料ではないため、すべてのログ行ではなく、通常はメトリクスハンドラーの内部で、リクエストごとに最大 1 回だけ呼び出してください。
  • クローンは禁止されています。 clone $worker\Error("Cloning OxPHP\\Server\\Worker is not allowed") をスローします。ワーカーハンドルは OS スレッドのアイデンティティを表しており、これをクローンすると、同じスレッドに対して 2 つ目のハンドルがあるかのような誤解を招きます。
  • OxPHP ホストの外部(例えば、SAPI をリンクする拡張機能が PHP CLI に読み込まれた場合)では、Worker::current() は依然としてインスタンスを返しますが、すべてのアクセサーはゼロ状態の値を返します。id()0startTime() はプロセスの開始時刻、requestCount()0rss() は現在の RSS、そして serve()InvalidServeContextException をスローします。

関連項目

  • ワーカーモード — 永続的な PHP プロセスと、一度だけブートストラップするパターンの概要
  • PHP 関数 — レガシーの oxphp_* フリー関数のリファレンス
  • Request API — リクエストごとのタイミングのための OxPHP\Http\RequestInterface::startTime()