【Laravel】Sail のデフォルト Web/AP サーバで複数リクエストを並列処理する
概要
Laravel Sail では複数のリクエストを並列で処理できないかと思ったら実はできました!
ついでに開発環境もちょっとだけ早くなったよ、という話です。
Laravel Sail 便利ですよね
現在のプロジェクトの開発環境は Laravel Sail を使用しています。
Sail を使用すれば簡単に Laravel の Docker 開発環境が作れます。
また、docker compose ~~~
のコマンドが sail up
のようにデフォルトでエイリアスが作られていて簡単に叩けるようになっていたりして便利です。
例えば、sail artisan
に続けてコマンドを実行すれば migrate
やtinker
などがコンテナに入らずに実行できます!
このように便利な Sail なのですが先日ひとつ問題が発生しました。
APIがタイムアウトするという事象が発生
システムA から システムB へ API で連携する改修を行っていました。
その中で以下のように相互に API を叩き合う処理を追加し試したところ処理が終わらないということが発生しました。
- システムAがBのAPI1を実行
- システムBはそのAPI1の処理の途中で、システムAのAPI2を実行
- システムBからの応答がなかったとしてシステムAの処理がタイムアウト
タイムアウトの原因
このタイムアウトの原因は Laravel Sail の Web/AP サーバがシングルプロセスだったためでした。
以下のようにお互いがお互いの処理完了を待ってしまった結果、タイムアウトしてしまいました。
- システムAはAPI1の応答を待っている ※この時点でひとつしかないプロセスを専有
- システムBはAPI1の途中でAPI2で情報を取得しようとするが、システムAはシングルプロセスなのでこれに応答できない
ただ、実装を見直した結果、相互にAPIを叩き合う必要はなかったのでこの問題は回避できました。
なんでシングルプロセスなの?
Laravel Sail は Web/AP サーバに PHP のビルドインサーバを使用しており、こちらが基本的にはシングルプロセスでしか動作しないためでした。
マニュアルの一番上に書いてありますね… 残念…
と思ったら実はできそう
この記事を書いていて気づいてしまったのですが、PHP7.4 以降であれば環境変数を指定することで並列で処理を実行できるようです…!
一番上に「単一のシングルスレッドプロセスしか実行しない」って書いてあったから騙された…!
ビルトインウェブサーバに対して複数のリクエストを並列で投げる必要があるテストコードのために、 複数のワーカーをフォークさせるよう設定できるようになりました。
サーバを起動する前に欲しいワーカーの数を PHP_CLI_SERVER_WORKERS 環境変数に設定してください。
試してみました
docker-compose.yaml
に以下のようにPHP_CLI_SERVER_WORKERS
環境変数を追加してコンテナを起動してみました。
environment: WWWUSER: '${WWWUSER}' LARAVEL_SAIL: 1 PHP_CLI_SERVER_WORKERS: 5 # 追加!
必ず呼び出される index.php などに sleep で5秒待機する処理を追加して、curl で同じ URL を取得するように複数のタブで並列に叩いてみました。
その結果、PHP_CLI_SERVER_WORKERS
を指定した場合だと並列で curl を実行してもほぼ同じタイミングで応答が返ってきました!
(環境変数を指定しない場合だと同タイミングではなく、先に叩いた curl の応答が返ってきた数秒後に次の応答が返ってきました)
少しだけ高速化
ふと思って開発環境で画面を開いて見たところ1〜2秒くらいですが表示速度が上がっていました。
特に意識してなかったのですが、今まではシングルプロセスだったのでフロントから並列で叩かれるAPIも直列で処理していたわけです。
これが、並列で処理して応答を返してくれるようになったので表示速度が少しだけあがりました!
ただ、あまり並列数を上げすぎるとどこかで処理が集中しすぎるのか応答が返ってこない API が出てくるためプロセス数は 3 程度に抑えるようにしました。
開発環境でも早いに越したことことはないのでラッキーでした!
おまけ:どこに Sail はビルドインサーバで動いてるって書いてるの?
ここの Tips に Sail で php artisan serve
が動いているという記載がありました。
そしてこちらのページにはSailへPHP開発サーバの代わりにOctaneを使い
とありました。
もっとわかりやすく書いてくれていたページがあった気がしたのですが見つけられなかった…!