新卒からずっと業務で読み書きしてるPHP。親のように思っているが実際のところなんとなくで書けてしまうので基礎的な部分が分かってないと思いchatGPTに聞きつつファクトチェックしつつ勉強してみました。
(ちなみにo3に聞いたら2割くらいしか理解できなかったのでいつもお世話になっている4oに頼んで噛み砕きながら理解していきました)
PHPはどうやって動いている?
ユーザー(ブラウザ)からリクエストが来たとき、PHP自体はそのリクエストを受け取ることはできない。
そのため、PHPの前段にapacheやnginxなどのwebサーバーを置き、リクエストはそこで受け取って、そこから裏側のPHPに通す。
PHP単体でもビルトインサーバーがあるのでリクエストを受け取ることは可能だがシングルスレッドプロセス(後述)でしか動かないので開発環境用などにしか使えない。
https://www.php.net/manual/ja/features.commandline.webserver.php
PHP内部での動き
前段のwebサーバーからリクエストが送られてきたときPHPはどのように動くのかという部分。
PHPは基本シングルスレッド、マルチプロセスで動く。
単一のスレッド内で、リクエストごとにプロセスを増やして処理する。
受けられるリクエスト数を増やしたい場合は、サーバー本体のメモリ容量内でプールサイズを増やして対応する。
PHP実行の種類
PHPの基本的な機能としては上記の通りだが、実際にPHPを実行する方法にはいくつか種類があり、プロセス管理の方法によって分類される。
webサーバーとプロセスを共有しないかつ起動済みのプロセスを使う(リクエストに応じてプロセスを開始しない)php-fpm(FastCGI Process Manager) が現在のデファクト。
以下の記事が分かりやすかったです。
webサーバーの種類(apache、nginx)
前段に置くwebサーバーとしての選択肢は主にapacheかnginxに絞られる。
歴史的にはapacheが古くから使われており、nginxが後発。
比較すると、
- apache
- マルチプロセッシングモジュール(MPM)で、利用用途に応じて変更可能。かつてのデフォルトはPHPと同じようにマルチプロセス方式。nginxと同じようにイベント駆動のモデルにもできるが、処理の仕組み上nginxよりは遅い。
- nginx
- イベント駆動・非同期I/O。リクエストごとにプロセスを増やさないため、C10K問題が起きない。
C10K問題
クライアントが約1万台に達すると、Webサーバーのハードウェア性能に余裕があるにもかかわらず、レスポンス性能が大きく下がる問題
どちらを選択するかは要件によるが、多くの場合は処理が軽く大量アクセスを捌けるnginx(+ php-fpm)の構成にしておけば問題ないと思う。
実際にホストする際には
今回はコンテナ化した上で、AWSの各種サービスでホスティングする場合にどのような構成にすべきか考える。
LaravelみたいなフルスタックフレームワークでWEBアプリを新規開発することを想定して、できるだけマネージドなECS(Fargate)とApp Runnerの2つを考えてみる。それぞれのサービスの詳細は今回割愛。
ECS(Fargate)
前述のnginx + php-fpmの構成にする場合、それぞれでイメージを用意してコンテナを分ける(docker公式としても1コンテナ=1責務というベストプラクティスを提唱している)。
そのため、1タスク内にnginx用のコンテナとphp-fpm用のコンテナを配置する構成になる。
App Runner
dockerイメージを用意するだけで(ほぼ)そのままアプリケーションをホストできる。
App Runnerではマルチコンテナ構成にできないので、php-apacheのようなモジュール版のapacheイメージ(または非公式のnginx+php-fpmが同居したイメージ)でシングルコンテナという構成をとる。
App Runnerのスケーリングはリクエスト数に応じてインスタンスが増えるため、適切にスケーリングができていればapacheで起こりうるC10K問題も起きない(可能性が高い)。
感想
こうして整理するととても勉強になった。調べてみるとどんどん分からないことが出てくるので今後深堀ってみたい。
実務だとAWSのサービス選定の基準になるのでこういう知識はインフラがクラウドで抽象化されたとしても必要になるからやっぱ体系的に理解しておくべきだと思った。