nginx+php-fpmからLaravel Octaneに変えてみた

こんにちは。元AI・IoTサービス開発部 から変わり、DXビジネス開発部となりました青木です。

Laravel Octaneなるものをドキュメントで見つけてからいつか手を出そうと思い時間が経ってしましました。 今回はOctaneの導入と、パフォーマンス改善結果などにも触れていきたいと思います。

Laravel Octaneとは

laravel.com

Laravel Octane supercharges your application's performance by serving your application using high-powered application servers, including Open Swoole, Swoole, and RoadRunner.

Open SwooleRoadRunnerの仕組みの上にLaravelアプリケーションの起動が出来るようになる仕組みです。

今回はOpen Swooleで開発を行ったためOpen Swoole中心に語ります。

従来では PHP-FPM + nginx の構成が一般的でしたが、Open Swooleでは予めプロセスを立ち上げておき、そのプロセスに対して非同期で処理を行う事で高速に処理が出来るようになる仕組みを持っており、リクエスト毎にプロセスを立ち上げていた従来の方法よりも高速に処理することが出来るようになります。

が、従来はプロセスを使い捨てしていた関係上メモリリークなどが起こりづらい状況が作れており、ある意味安全な状態だったもののOpen Swooleに置き換えることでそのあたりも考慮する必要が出てきました。Open Swooleを利用する際に詰まる部分なので注意してください。

Laravel Octaneの導入

既にLaravelでアプリケーションを開発している方も、新規で開発される方も以下のコマンドでサクッと導入出来ます。

composer require laravel/octane
php artisan octane:install

開発時は普段通り php artisan serve で立てられますが、Laravel Octane独自の機能を利用している場合は開発時もOctane経由で起動する必要があります。

php artisan octane:start

このコマンドは、サーバアプリケーションを提供する場合にも利用するコマンドとなります。

php artisan serveで起動した場合は開発時のみの利用にとどめてください

octane:start ではローカルにOpenSwooleを入れるなどの対応が必要で少々面倒なのでDockerで実行します。

Laravel OctaneをDockerで実行する

github.com

有志の方がご提供頂いているDockerfileを利用してみます。

Dockerfileをプロジェクトルートに入れ以下のコマンドで起動します。

docker build -t octane_test .
docker run --name octane_test -p 8000:8000 --env-file .env octane_test

必要に応じてVolumeMountを実施してください

Octaneに変えた効果

良かった点

  • レスポンスが早くなった
  • リソース消費量が減った
  • PHP-FPMとnginxの両方を管理しなくて良くなった

レスポンスが早くなった, リソース消費量が減った

マシンスペックにもよりますが、単純にレスポンスを返却するだけの簡単なエンドポイントであれば概ね 10ms ~ 50ms 程度で返却されるようになりました。 nginx+php-fpmでは同スペックで 100ms ~ 200ms 程度でしたので相当早くなっていることがわかります。

レスポンスが早いこととリソース消費量が減ったのは相関関係にあり、ある程度スペックを絞ってもそれなりのレスポンスを返却してくれるようになりました。

開発のみの環境ですが、k8s上のリソース指定は以下のものでも十分に動作しています。

  resources:
    limits:
      cpu: 100m
      memory: 128Mi
    requests:
      cpu: 50m
      memory: 64Mi

PHP-FPMとnginxの両方を管理しなくて良くなった

タイトルの通りで、k8sでも複数のPodやServiceに分かれてデプロイされている関係上リソース管理が2倍になっていたところ、上記記載のDockerImageに変更する事で管理を一つにすることが出来るので便利です。

(nginx ingress を使うことでそのあたりは避けられる可能性もありますが....)

気になった点

  • メモリリークしている

メモリリークしている

開発時に利用している閉鎖環境でしばらく様子をうかがっていたところ、メモリーリークを発見しました。 k8sにデプロイしているPodのメモリをDatadogにて集計し、確認をしているのですが画像のように確かにメモリリークされています。

https://cdn-ak.f.st-hatena.com/images/fotolife/o/optim-tech/20230713/20230713154954.png

laravel.com

公式ドキュメントでも言及されていますが、普段通りのPHPの使い方を気にせず利用していると意図しないメモリーリークが発生する可能性があります。

github.com

こちらのようにLaravelでは非常に利用されるHttpファサードを普通に使うとメモリリークしてしまいます。 今まで普通に利用していたファサードなどを使う場合は簡単にメモリリークされてしまうので要注意です。

GuzzleClientを使うことで解消されるようですが、既存のLaravelサービスをOctaneに変更する等の場合は必ず影響調査を実施した方が良さそうです。

多少のメモリーリークであれば以下の --max-requests の値を変更するなどしてWorkerの再起動設定を実施すれば通常的に運用する事は可能ですが、 不慮の事故を避けるため解消しておいた方が良いかと思われます。

github.com

本件ではHttpファサードを使わないようにしてみたところ以下のようなメトリクスとなり症状は改善されました。

https://cdn-ak.f.st-hatena.com/images/fotolife/o/optim-tech/20230713/20230713154957.png

さいごに

Laravel Octane自体は公式ドキュメントにも記載されているようにアプリケーション高速化のデファクトになっていくと思いますので、なるべくキャッチアップしていこうと思います。


オプティムでは、一緒に働く仲間を募集しています。興味のある方は、こちらをご覧ください。

www.optim.co.jp