はじめに
CGI。前から存在だけは知っていて、でも少ーし調べたところで「?」「サーバーサイドで動作するプログラムと何が違うんや」という感想しか生まれず、ずっと目を背け続けていたそんな彼と今日、ようやく向き合ってみました。
長らく気になっていたことが頭の中で整理できた喜びのあまり 急いでまとめたので、誤った表現もあるかもしれませんがその際はご指摘いただけますと幸いです。
概要
- CGIとは
- FastCGIとは
- PHP-FPM?mod_php?
- Dockerイメージの例
CGIとは
CGI(Common Gateway Interface)は、Webサーバーと外部プログラム(PHPなど)の間で情報をやりとりするための標準的なインターフェース(プロトコル)です。
(現在ではCGIに似た役割を担う別の方法もありますが、)基本的にこのような仕組みがないとサーバーサイドでプログラムを実行することはできません。←知らなかった...
※厳密には「実行できない」というよりWebサーバーから「呼び出すことができない」?(実行自体はランタイムがあれば可能なため)
処理の流れとしては
- Webサーバーがクライアントからリクエストを受ける
- WebサーバーはCGIプロトコルによってリクエストを転送し、外部プログラム(PHPスクリプト等)を実行
- その結果をWebサーバーが受け取り、クライアントへ返却
という感じです。
元々私はCGIがなんだかよくわからず、かつWebサーバー/APサーバーを一から構築した経験がなかったため、「サーバーサイドでプログラムを実行させるなんて、LaravelやNode.jsだって(ローカルやDockerコンテナ上では)普通に動いてるし要るの?」と考えていました。
また、「PHP:x.x-apache」や「PHP:x.x-fpm」のようなDockerイメージを使用して起動したコンテナで(当たり前ですが)「普通にPHP動いとるがな?」と、なんとも恥ずかしい勘違いをしていました。
※これらのDockerイメージについては後述します。
私なりにまとめると、
- 元々、Webサーバーで静的コンテンツを提供するだけなら問題なかった
- プログラムを実行して動的コンテンツを生成したい場合、Webサーバーの機能だけではサーバーサイドでプログラムを実行することができないため、その基盤としてCGIが必要
- 「Webサーバー+PHP+CGIでまとめた1つのサーバー」でも「Webサーバー/PHP+CGIのAPサーバー」でも可。いずれにせよ、WebサーバーからCGIに対して指示を行い、PHPスクリプトを実行するような仕組みが必要
となります。
FastCGIとは
簡単に言えばCGIの強化版です。
CGI
- ユーザーからのリクエストのたびにプロセスの生成と破棄を行う
FastCGI
- 初回リクエストのタイミングで起動したプロセスをメモリで保持し、以降のリクエストに対してはそのプロセスを実行するため、サーバーの負荷の低減や処理速度の向上につながる
上記以外にも違いはありますが、大きな違いとしてはこんな感じです。
PHP-FPM?mod_php?
現在、PHPをサーバーサイドで実行するための仕組みとして主流なものが2種類あります。
PHP-FPM(FastCGI Process Manager)
- 前述したFastCGIの仕組みを取り入れたもの
- PHPをFastCGIとして動作させ、NginxやApacheのようなWebサーバーと通信する
- 処理の流れ(CGIと基本的に変わりませんが)
- クライアントがサーバーへのリクエストを送信
- WebサーバーがFastCGIプロトコルを使用してリクエストをPHP-FPMに転送
- PHP-FPMがスクリプトを実行し、生成されたHTMLやデータをWebサーバーに返却
- Webサーバーからクライアントに返却
mod_php
- ApacheなどのWebサーバーにPHPをモジュールとして組み込む方法
- ここでいう「モジュール」はWebサーバーが直接実行可能な機能のこと
- こうすることで、Webサーバーは直接PHPスクリプトを実行可能
- 処理の流れ
- クライアントがWebサーバーへのリクエストを送信
- Webサーバーが直接PHPモジュールを呼び出し、スクリプトを実行
- 生成されたHTMLやデータをクライアントに返却
イメージとしては、
- PHP-FPMがCGI(FastCGI)を介してプログラムを実行
- mod_phpはWebサーバーが直接プログラム(実際にはモジュール)を実行
という感じです。
Dockerイメージの例
普段、何気なく使ってたDockerイメージも掘り下げてみるとこんな違いがありました。
php:x.x-fpm
- Webサーバーから外部接続する、PHPプログラム専用のサーバーとなる(別でWebサーバーが必要)
- PHP-FPM の仕組み
- Nginx+PHP-FPMの構成が一般的
- フロントエンドサーバー(Nginx)とバックエンドサーバー(PHP-FPM)を分離できるため、スケーラブルなアーキテクチャが構築しやすい
- 高パフォーマンス、スケーラビリティが高い、Nginxなどのウェブサーバーと連携が可能
- 高トラフィックのウェブサイト、大規模なアプリケーション、スケーラブルなインフラ構築
php:x.x-apache
- PHPがApache Webサーバーのモジュールとして組み込まれている(Webサーバー上でそのままPHPプログラムを実行可能)
- mod_php の仕組み
- セットアップが簡単、単一のコンテナで完結
- 小規模なプロジェクト、開発やテスト環境、シンプルなデプロイメント
最後に
私自身 Angular+NestJSでの開発経験が長かった(かつリリース経験が少ない)ため、Webサーバー、アプリケーションサーバー、Apache、Nginx...といったことに疎く、SPAから非同期でAPIを呼び出すため、サーバーにはAngularの実行ファイル+APIサーバーを置いておく、といった雑な感覚のままでいました。
一般的にはWebサーバー(Apache、Nginx)で静的コンテンツの供給、アプリケーションサーバーで動的コンテンツを生成し、Webサーバーに返却、という流れが多いと思いますが、このあたりの感覚がなかったことで理解に時間がかかったというのもあると思います。
(Webサーバーでプログラムが実行できないとは???のような混乱を起こす原因に)
CGIがプロトコルであること、Webサーバーから外部(アプリケーションサーバー、あるいはWebサーバー内の)プログラムを呼び出すために必要であることは、Webアプリケーションを開発する上で非常に重要な仕組みだと思います。
苦手意識の強い部分でしたが、かなり勉強になりました。