はじめに
FrankenPHPはGoでCaddyウェブサーバー上に構築された、モダンなPHPアプリケーションサーバーです。高速なパフォーマンスと豊富な機能を提供し、主要なフレームワークをネイティブサポートしていることで注目を集めています。一方で安定性の問題も報告されており、採用には十分な検討が必要です。
TECH PLAYでは進行中のシステムリプレイスの一環として、このFrankenPHP導入にトライしてみました。その体験談をまとめましたので、これからFrankenPHPの導入を検討されている方の参考になれば幸いです。
FrankenPHPとは?
FrankenPHPは、PHPのアプリケーションサーバーです。PHPコードの実行を高速化するための技術が盛り込まれていて、例えばメモリにコードを保存し、それを直接読み込むことで高速な処理を実現するなどしています。
GoでCaddy Webサーバー上に構築されたFrankenPHPはオールインワンソリューションであり、単一のバイナリで動作します。そのため従来のPHP-FPMとNginxといった組み合わせが不要で、セットアップが簡単なことも特徴の一つです。
FrankenPHPの主な特徴をまとめると以下のようになります。
- 高速パフォーマンス:PHP-FPMより約3.5倍速いとされています。
- ワーカーモード:アプリケーションをメモリに保持し、高速な応答を実現。
- 自動HTTPS:セキュリティ設定が簡単である。
- HTTP/2、HTTP/3サポート:最新のウェブ技術に対応。
- 主要フレームワーク対応:Laravel、Symfony、WordPressなどをネイティブサポート。
FrankenPHPは、PHPアプリケーションの開発と運用を効率化し、WEBサービスのパフォーマンスを向上させる強力なツールとして期待されています。
TECH PLAYが抱えていた課題
これまでTECH PLAYはNginxとPHP-FPMで運用しており、以下のような課題を感じていました。
- NginxとPHP-FPMの二つのコンテナを立ち上げる必要があり、インフラの構成が複雑になってしまう。システムが落ちてしまった時にどちらが原因かを確認するのも手間である。
- WEBサイトの動作スピードの伸び悩み。
- ホットリロードを活用したい。
- メモリをもっと効率的に活用したい。
FrankenPHPによる課題解決への期待
まずFrankenPHPというパッケージの中にはWebサーバーとアプリケーションサーバーが含まれていることにより、複数のコンテナを管理する必要がなくなると考えました。
そしてPHP-FPMはリクエストごとにコードを読み込むのに対し、FrankenPHPはメモリに保存して読み込むので、速度が速いという点はWEBサイトのスピード向上のために特に期待が高かったです。
さらにこの機会にホットリロード機能の有効活用を考えました。ホットリロード自体は他のWebサーバーでも可能ですが、今まであまり活用できていませんでした。ホットリロードを活用できればPHPコードを変更した際にブラウザをリロードせずに即時反映されるので、開発効率が向上します。
FrankenPHP最大の特徴は処理速度
FrankenPHPにはクラシックモードとワーカーモードという2つの動作モードがあります。クラシックモードはPHP-FPMとそれほど変わりませんが、ワーカーモードではメモリにPHPアプリを保存して処理するので、パフォーマンスが約3倍向上すると言われています。
実験としてAWSのFargateにPHP-FPMとFrankenPHPのサーバーをそれぞれ立ち上げ、TECH PLAYのある機能にリクエストを大量に投げてパフォーマンスを比較してみました。
受ける側のサーバーは1台とし、投げる側のサーバーを5台それぞれ10並列で用意した上で3分間リクエストを投げ続けるというものです。
結果として、確かにFrankenPHPの方が約3倍のリクエストを処理できることが分かりました。具体的にはPHP-FPMが826リクエストを処理するのに対し、FrankenPHPは2770リクエストを処理できました。
FrankenPHPの処理速度の高さは、実際に本番で運用しても体感することができています。
FrankenPHPには新たなHTTPステータスコードであるEarly Hintsが導入されています。これを活用することができれば、さらにサイトの高速化を進めることができるため、検証を進めていきたいと考えています。Early Hintsはリクエストを送った後、レスポンスが返ってくる前に、事前にJavaScriptやCSSを読み込むことができる機能です。これにより、ページの読み込み速度が向上することが期待されています。
他の選択肢との比較
アプリケーションサーバーの移行にあたっては、RoadRunnerやSwooleも検討しましたが、実験の結果FrankenPHPのパフォーマンスが一番高いと判断しました。
実験は多数の演算を繰り返し実行するものです。
ローカルで行ったswooleとfrankenPHPの検証
負荷かけるためのコマンド(apache bench)
同時実行数20、総リクエスト数1000ab -c 20 -n 1000 url
実行されたコード
Route::get('/test', function () {
$sum = 0;
for ($i = 0; $i < 100000; $i++) {
$sum += $i;
}
return '計算が完了しました。';
});
この実験の結果、DebianイメージのFrankenPHPがもっとも良い結果となりました。
導入の難易度
PHPフレームワークとしてLaravelを採用しているのであれば、FrankenPHPとの連携はとても簡単で、公式のDockerコンテナを使用することで導入の敷居が低くなります。TECH PLAYではLaravelを使用しているため、実際に導入コストは低いと感じました。他のフレームワークを使用している場合は、もう少し難易度が上がるかもしれません。
私たちは公式のDockerコンテナを使用し、Laravelアプリケーションを一度メモリに読み込み、高速でリクエストを処理するミドルウェアであるLaravel Octaneという技術を使ってFrankenPHPを起動する方法を取りました。これにより、導入が非常に簡単になりました。
FrankenPHPのチューニング
FrankenPHP自体のチューニングとして、ワーカーの数を決めたり、ログの出力を最小限に抑えたり、OPcacheなどのキャッシュ系の最適化を行いました。これにより、パフォーマンスをさらに向上させることができました。ワーカーの数を決めるためには負荷試験も実施しています。
また、Dockerイメージの選定も重要で、適切なイメージを選ぶことでチューニング少なくパフォーマンスを最適化できます。
具体的にはAlpineイメージを使用するか、Debianイメージを使用するかなのですが、先述の通り私たちはそれぞれのイメージで多数の演算を行う検証をしました。結果として最も処理速度が速いと判断できた、Debianベースのイメージを選択することにしました。
FrankenPHP利用時の注意点
FrankenPHPを使用する際は、いくつかの注意点があります。
メモリリーク
FrankenPHPはアプリケーションをメモリに保存するという特性上、PHP-FPMと同じ感覚で使用しているとメモリリークを起こす可能性があります。メモリリークを起こすとシステム全体のパフォーマンスが低下してしまう恐れがあります。
静的な変数の取り扱いには注意
これもFrankenPHPはアプリケーションをメモリに保存するという特性上ですが、静的変数にデータを保存すると、リクエストごとにリフレッシュされないため、扱いを間違えると情報漏洩のリスクがあります。
例えば静的変数に個人情報を保存してしまうと、他のユーザーにその情報が見えてしまうリスクがあるのです。静的変数の扱いに注意し、コードを見直して漏洩を防ぐための対策を講じる必要があります。
クラスのインスタンス化について
クラスのインスタンス化に関しても注意が必要です。例えば、リクエストごとにインスタンス化されるクラスは問題ありませんが、一度しかインスタンス化されないクラスはメモリにキャッシュされてしまうため、変更が反映されないことがあります。
特にシングルトンパターンを使用する場合は注意が必要です。
サポートされていないPHPの拡張機能がある
FrankenPHPはすべてのPHP拡張機能をサポートしているわけではなく、特に利用が多いOpenSSLにはまだバグがあるようなので、公式サイトを参考にして慎重に導入と検証を進めましょう。
今後改善されていくとは思いますが、FrankenPHPがサポートしていないPHP拡張機能については事前に確認し、代替策を検討する必要があります。
設定ファイル
Caddyというウェブサーバーを使用しており、Nginxとは設定ファイルの書き方が異なります。Caddyの設定ファイルの書き方に慣れる必要があります。
FrankenPHPの安定性
今のところ、私たちの環境での運用は安定しています。FrankenPHPに移行したことに起因するエラーは無さそうです。長期的な安定性についてはまたレポートしようと思います。
ローカル環境での開発中にいくつかのバグが発生しました。特に、ホットリロード機能に関するバグが報告されており、設定ファイルの書き方によってはブラウザがリロードし続ける問題が発生することがあります。
Laravel Octane側でホットリロードの設定を行うと、この問題が発生することがわかったため、Caddyファイル側でホットリロードの設定を行うことで回避できました。
FrankenPHPの今後
FrankenPHPは現時点で頻繁にアップデートされており、今後も性能の向上が期待できると予想しています。パフォーマンスの更なる最適化もあるでしょうし、バグフィックスによる安定性の向上もあると思います。各社クラウドプラットフォームとの連携も期待したいところです。
まとめと考察
FrankenPHPは、PHP-FPMに代わる新しいアプリケーションサーバーとして、高速な処理速度と簡単な設定を提供します。TECH PLAYのエンジニアチームが実際に導入した結果、処理速度が約3倍向上し、開発効率も大幅に改善されました。しかし、メモリリークのリスクやサポートされていないPHP拡張機能、設定ファイルの違いなど、注意すべき点もいくつかあります。導入前には確認用の環境を用意するなどして慎重な調査や実験が必要です。
FrankenPHPは、特に高速な処理が求められる環境や、開発効率を重視するプロジェクトに適しています。Laravelとの連携が容易であるため導入の敷居が低く、Laravelを使用しているプロジェクトには特におすすめです。
今後のアップデートやコミュニティの発展により、さらに使いやすくなることが期待されます。FrankenPHPの導入を検討している方は、この記事を参考にしてメリットとデメリットの検証を実施してみてください。