このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。
このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。
このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。
デフォルトでは、FrankenPHPはパフォーマンスと使いやすさのバランスが取れた構成を提供するよう設計されています。 ただし、適切な設定により、パフォーマンスを大幅に向上させることが可能です。
デフォルトでは、FrankenPHPは利用可能なCPU数の2倍のスレッドとワーカー(ワーカーモードで)を開始します。
適切な値は、アプリケーションの書き方、機能、ハードウェアに大きく依存します。
これらの値を調整することを強く推奨します。最適なシステムの安定性のためには、num_threads x memory_limit < available_memoryとすることをお勧めします。
適切な値を見つけるには、実際のトラフィックをシミュレートした負荷テストを実行するのが最も効果的です。 そのためのツールとして、k6やGatlingが有用です。
スレッド数を設定するには、php_serverやphpディレクティブ内のnum_threadsオプションを使用してください。
ワーカー数を変更するには、frankenphpディレクティブ内のworkerセクションにあるnumオプションを使用してください。
max_threads実際のトラフィックがどのようなものになるかを正確に把握できれば理想ですが、現実のアプリケーションでは
予測困難な挙動が多いものです。max_threads設定 により、FrankenPHPは指定された制限まで実行時に追加スレッドを自動的に生成できます。
max_threadsはトラフィックを処理するために必要なスレッド数を把握するのに役立ち、レイテンシのスパイクに対してサーバーをより回復力のあるものにできます。
autoに設定すると、制限はphp.iniのmemory_limitに基づいて推定されます。推定できない場合、
autoは代わりにnum_threadsの2倍がデフォルトになります。autoは必要なスレッド数を大幅に過小評価する可能性があることに留意してください。
max_threadsはPHP FPMのpm.max_childrenに似ています。主な違いは、FrankenPHPがプロセスではなくスレッドを使用し、
必要に応じて異なるワーカースクリプトと「クラシックモード」間で自動的に委譲することです。
ワーカーモードを有効にするとパフォーマンスが劇的に向上しますが、 アプリがこのモードと互換性があるように適応する必要があります: ワーカースクリプトを作成し、アプリがメモリリークしていないことを確認する必要があります。
公式Dockerイメージと私たちが提供するデフォルトバイナリのAlpine Linuxバリアントは、musl libcを使用しています。
PHPは、従来のGNUライブラリの代わりにこの代替Cライブラリを使用すると遅くなることが知られており、 特にFrankenPHPに必要なZTSモード(スレッドセーフ)でコンパイルされた場合です。高度にスレッド化された環境では、差が大きくなる可能性があります。
本番環境では、glibcにリンクされたFrankenPHPを使用することをお勧めします。
これは、Debian Dockerイメージを使用するか、公式パッケージ (.deb, .rpm, .apk) を使用するか、あるいはFrankenPHPをソースからコンパイルすることで実現できます。
より軽量で安全なコンテナのためには、Alpineよりも強化されたDebianイメージを検討することをお勧めします。
FrankenPHPはGoで書かれています。
一般的に、Go runtimeは特別な設定を必要としませんが、特定の状況では、 特定の設定でパフォーマンスが向上する場合があります。
おそらくGODEBUG環境変数をcgocheck=0に設定したいでしょう(FrankenPHP Dockerイメージのデフォルト)。
FrankenPHPをコンテナ(Docker、Kubernetes、LXC…)で実行しており、コンテナで利用可能なメモリを制限している場合は、
GOMEMLIMIT環境変数に利用可能なメモリ量を設定してください。
詳細については、Go ランタイムを最大限に活用するために、この主題に特化したGoドキュメントページを読むことを強く推奨します。
file_serverデフォルトでは、php_serverディレクティブは自動的にファイルサーバーを設定して
ルートディレクトリに保存された静的ファイル(アセット)を配信します。
この機能は便利ですが、コストがかかります。 無効にするには、以下の設定を使用してください:
php_server {
file_server off
}
try_filesphp_serverは、静的ファイルとPHPファイルに加えて、アプリケーションのインデックスファイル
およびディレクトリインデックスファイル(/path/ -> /path/index.php)も試行します。ディレクトリインデックスが不要な場合、
次のようにtry_filesを明示的に定義して無効にできます:
php_server {
try_files {path} index.php
root /root/to/your/app # ここで root を明示的に追加すると、キャッシュの効率が向上します
}
これにより、不要なファイルの操作の回数を大幅に削減できます。 上記の構成をワーカーモードに相当させると、次のようになります:
route {
php_server { # file server が全く不要な場合は "php_server" の代わりに "php" を使用します
root /root/to/your/app
worker /path/to/worker.php {
match * # すべてのリクエストを直接ワーカーに送信します
}
}
}
ファイルシステムへの不要な操作を完全にゼロにする代替アプローチとして、phpディレクティブを使用し、
パスによってPHPファイルとそれ以外を分ける方法があります。アプリケーション全体が1つのエントリーファイルで提供される場合、この方法は有効です。
たとえば/assetsフォルダの背後で静的ファイルを提供する設定は次のようになります:
route {
@assets {
path /assets/*
}
# /assets 以下のリクエストはファイルサーバーが処理する
file_server @assets {
root /root/to/your/app
}
# /assets 以外のすべてのリクエストは index または worker の PHP ファイルで処理する
rewrite index.php
php {
root /root/to/your/app # ここで root を明示的に追加すると、キャッシュの効率が向上します
}
}
rootおよびenvディレクティブ内では、プレースホルダーを使用できます。
ただし、これによりこれらの値をキャッシュすることができなくなり、大幅なパフォーマンスコストが発生します。
可能であれば、これらのディレクティブではプレースホルダーの使用を避けてください。
resolve_root_symlinkデフォルトでは、ドキュメントルートがシンボリックリンクである場合、FrankenPHP はそれを自動的に解決します(これは PHP が正しく動作するために必要です)。 ドキュメントルートがシンボリックリンクでない場合、この機能を無効にできます。
php_server {
resolve_root_symlink false
}
この設定は、rootディレクティブにプレースホルダーが含まれている場合にパフォーマンスを向上させます。
それ以外の場合の効果はごくわずかです。
ログ出力は当然ながら非常に有用ですが、その性質上、 I/O操作およびメモリ確保が必要となり、パフォーマンスを大幅に低下させます。 ログレベルを正しく設定し、 必要なもののみをログに記録するようにしてください。
FrankenPHPは公式のPHPインタープリターを使用しています。 通常のPHPに関するパフォーマンス最適化はすべてFrankenPHPでも有効です。
特に以下の点を確認してください:
realpathキャッシュがアプリケーションのニーズに合わせて十分な大きさであること詳細については、Symfonyの専用ドキュメントエントリをお読みください (Symfonyを使用していなくても、多くのヒントが役立ちます)。
アプリケーションが、高負荷時に不安定になったり、常に10秒以上応答にかかるAPIのような遅い外部サービスと連携することはよくあります。 このような場合、スレッドプールを分割して専用の「遅い」プールを持つことが有益です。 これにより、遅いエンドポイントがすべてのサーバーリソース/スレッドを消費するのを防ぎ、コネクションプールと同様に、遅いエンドポイントへのリクエストの同時実行数を制限できます。
example.com {
php_server {
root /app/public # アプリケーションのルート
worker index.php {
match /slow-endpoint/* # パスが /slow-endpoint/* のすべてリクエストはこのスレッドプールによって処理されます
num 1 # /slow-endpoint/* に一致するリクエストに対しては最低1スレッド
max_threads 20 # 必要に応じて、/slow-endpoint/* に一致するリクエストに対して最大20スレッドまで許可します
}
worker index.php {
match * # 他のすべてのリクエストは個別に処理されます
num 1 # 遅いエンドポイントがハングし始めても、他のリクエストには最低1スレッド
max_threads 20 # 必要に応じて、他のリクエストに対して最大20スレッドまで許可します
}
}
}
一般的に、メッセージキューなどの適切なメカニズムを使用して、非常に遅いエンドポイントを非同期的に処理することも推奨されます。
このページを編集