Laravelに (Octaneと一緒に)RoadRunner Jobsを導入する
初めに
前回の記事で LaravelにOctane/RoadRunner を導入した際に、ついでにRoadRunner Jobsを導入して使ってみた結果を書きました。
ですが実際の導入の仕方を書いていなかったので書きます。
PHPのバージョン:8.3
Laravelのバージョン:10
Octaneのバージョン:2.4
RoadRunnerのバージョン:2024-2
Octane・RoadRunnerのインストール
公式のやり方に従って、OctaneとRoadRunnerを導入します(説明は割愛)
RoadRunner Jobsのインストール
公式のやり方に従って RoadRunner JobsのPHP側ライブラリを導入してください
(RRサーバーには標準でインストール済み)
Octaneの起動の仕方を変える
Octaneを使ってRoadRunnerを導入したときに1点問題があってそれは、
Octaneを使ってRoadRunnerを導入すると、RoadRunnerの標準的な設定ファイルである .rr.yaml
が生成されず、効かない状態になっています。
RoadRunner Jobsを使いたい場合、自分でワーカースクリプトを用意して、JobのリクエストとHTTPリクエストを分岐させて処理する必要があります。なのでいくつか修正をして、
-
rr.yaml
を正常に読み込むようにする -
カスタムワーカースクリプトが動作するようにする
必要があります。それではやってみましょう。
Octane -> RoadRunnerへの設定の渡し方の問題でしかないので、今後のバージョンアップで変わる可能性が十分にあることをご留意ください。
その場合、
vendor/laravel/octane/src/Commands
以下のPHPファイルを見て修正してください
Octaneの起動コマンドを変える
導入時はOctaneの起動コマンドに色々なオプションがついていると思うのですが、それを必要最低限にします
導入時に起動コマンドがどうなっているのか覚えていないので、私のプロジェクトの現状のコマンドを下に示します。
php -d variables_order=EGPCS /var/www/html/artisan octane:start --server=roadrunner --rpc-host=0.0.0.0 --rpc-port=6001
config/octane.php
の修正
以下の記述を追加してください
rr-worker.php
はカスタムワーカースクリプト名です。
'host' => env('OCTANE_HOST', '0.0.0.0'),
'port' => env('OCTANE_PORT', '8080'),
'roadrunner' => [
'command' => env('OCTANE_ROADRUNNER_COMMAND', 'rr-worker.php'),
]
.rr.yaml
の記載
公式を参考に記載してみてください
参考に私のプロジェクトの設定を挙げます。
色々いじくり回しているので変なところがあるかもしれません
カスタムワーカースクリプト
カスタムワーカースクリプトを作ります。
ワーカースクリプトはRoadRunnerが起動したワーカーのエントリポイントに当たるPHPスクリプトです。基本的な動作としては
- リクエストの待ち受け
- リクエストのRouting (リクエストの種類や起動すべきJobを判別)
を行います。
こちらも公式を参考に書いてくださいと言いたいところですが、Octane経由で導入した場合すでにOctaneのワーカースクリプトがあり、そちらとの兼ね合いがあります。
以下に私の例を示します。
rr-worker.php
#!/usr/bin/env php
<?php
namespace Composer;
require __DIR__ . '/vendor/autoload.php';
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
use Spiral\RoadRunner\Environment;
use App\Enums\Console\RoadRunnerModes;
use App\Console\RoadRunner\Dispatchers\JobDispatcher;
// Create environment
$env = Environment::fromGlobals();
$jobDispatcher = new JobDispatcher();
if($env->getMode() === RoadRunnerModes::Http->value) {
// HTTP リクエストの場合Octane側のスクリプトを起動する
return include __DIR__ . '/vendor/bin/roadrunner-worker';
} else if ($jobDispatcher->canServe($env)) {
// Job リクエストの場合、JobDispatcherを使って処理を行う
return $jobDispatcher->serve(__DIR__);
}
$env = Spiral\RoadRunner\Environment::fromGlobals();
でRRの環境変数を取得してHTTPリクエスト用のワーカーか判定し、HTTPリクエストならばOctaneが用意したワーカーに処理を渡しています。
それ以外の場合自作した JobDispatcher
と言うクラスに処理を渡しています。
App\Enums\Console\RoadRunnerModes
はリクエストの種類を列挙しているだけです
参考
$jobDispatcher->canServe($env)
はリクエストがJobかどうか判定しているだけです
JobDispatcher
長いのでGistにします
ポイントとしては
(正直これらの役割についてはあやふやなので、ご興味のある方はRoadRunnerやOctaneのコードリーディングを頑張ってみてください!)
ここでJobごとの分岐をおこなっています。
$nameにはJobのクラス名を渡す想定です。これはJobをDispatchするときにパラメータとして設定可能です(後述)。もちろん別のパラメータでも良いです。
Laravel\Octane\Worker::handleTask($job)
で渡した$jobをクロージャとして実行してくれます。
Jobのディスパッチ
Jobをディスパッチする場合次のようにしてみてください
$rpc = Spiral\Goridge\RPC\RPC::create('tcp://127.0.0.1:6001');
$jobs = new Spiral\RoadRunner\Jobs\Jobs($rpc);
$payload = [
(任意)
];
$queue = $jobs->connect('local');
$task = $queue->create(
XXXJob::class, // Jobのクラス名
json_encode($payload, JSON_UNESCAPED_UNICODE)
);
$queue->dispatch($task);
これでうまくいくはずです。
長々とした説明になりましたが参考にしてOctane + RoadRunner Jobsを導入してみてください!
Discussion