hysryt / wiki

https://hysryt.github.io/wiki/
0 stars 0 forks source link

CGI #166

Open hysryt opened 3 years ago

hysryt commented 3 years ago

CGI

WebサーバーがCGIプログラムを呼び出すときのデータの受け渡し方法及びデータ内容についての規約。 RFC3875で定義されている。

CGIプログラムは実行可能プログラムとして呼び出される。 リクエストの度にプログラム(プロセス)を実行するため、パフォーマンスが悪い。 この欠点を補うためにFastCGIが生まれた。

RFC3875 https://wiki.suikawiki.org/n/RFC%203875

Webサーバーの役割

  1. クライアントからのリクエストを受け取る
  2. リクエストを処理するCGIスクリプトを選択する
  3. クライアントのリクエストをCGIリクエストに変換する
  4. スクリプトを実行する
  5. CGIレスポンスをクライアントのレスポンスに変換する
hysryt commented 3 years ago

FastCGI

Open Market社によって開発された仕様。 CGIの欠点(リクエストごとにプロセスを起動するためパフォーマンスが悪い)を補っている。 FastCGIではリクエストの都度プロセスを起動するのではなく、1度起動したプロセスを使い回す。

Perlなどを使用する場合、最初にまずPerlスクリプトを実行する(この時新しいプロセスが起動される) レスポンスを返した後もPerlスクリプトは動作し続け、次のリクエストを待つ。 そのため、以下のようにPerlスクリプト側でFastCGIへの対応が必要となる。 (while文でFastCGIリクエストを繰り返し受け続ける)

#!/usr/bin/perl

use CGI::Fast qw(:standard);
while (new CGI::Fast) {
  print "Content-type: text/html \n\n";
  print "Hello";
}

PHPの場合はphp-fpmを使用する。 php-fpmがプロセスとして起動し、FastCGIリクエストを待ち受ける。 リクエストが来たら指定のPHPスクリプトを読み込み、動作させる。 レスポンスを返したら再びFastCGIリクエストを待ち受ける。 このようにFastCGIのリクエストの受付はphp-fpmが受け持つため、PHPスクリプト側でFastCGIへの対応は必要ない。

Perlの場合
Webサーバ <-> Perlスクリプト(FastCGIプロセス)

PHPの場合
Webサーバ <-> php-fpm(FastCGIプロセス) <-> PHPスクリプト

もしかしたらPerlにもphp-fpmのようなものがあるかもしれない。


参考 https://perldoc.jp/docs/modules/CGI-2.89/CGI/Fast.pod

hysryt commented 3 years ago

CGI と FastCGI の比較

環境

CGI設定

コード

#!/usr/bin/perl
print "Content-type: text/html \n\n";
print "Hello";

apache2.conf 設定

AddHandler cgi-script .cgi

FastCGI設定

コード

#!/usr/bin/perl
use CGI::Fast qw(:standard);
while (new CGI::Fast) {
  print "Content-type: text/html \n\n";
  print "Hello";
}

apache2.conf 設定

AddHandler fcgid-script .fcgi

計測

計測にはabコマンドを使用する。 総リクエスト数10000件、同時接続数100。

CGI

$ ab -n 10000 -c 100 http://localhost:8080/test.cgi
...
Concurrency Level:      100
Time taken for tests:   17.619 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1560000 bytes
HTML transferred:       50000 bytes
Requests per second:    567.56 [#/sec] (mean)
Time per request:       176.194 [ms] (mean)
Time per request:       1.762 [ms] (mean, across all concurrent requests)
Transfer rate:          86.46 [Kbytes/sec] received
...

FastCGI

$ ab -n 10000 -c 100 http://localhost:8080/test.fcgi
...
Concurrency Level:      100
Time taken for tests:   14.607 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1600000 bytes
HTML transferred:       50000 bytes
Requests per second:    684.63 [#/sec] (mean)
Time per request:       146.065 [ms] (mean)
Time per request:       1.461 [ms] (mean, across all concurrent requests)
Transfer rate:          106.97 [Kbytes/sec] received
...

1秒に処理したリクエスト数がCGIの方は567.56件、FastCGIの方は684.63件なので、FastCGIの方が処理が速いことがわかる。


ちなみに...

mod-php

Concurrency Level:      100
Time taken for tests:   8.394 seconds
Complete requests:      10000
Failed requests:        0
Non-2xx responses:      10000
Total transferred:      4530000 bytes
HTML transferred:       2730000 bytes
Requests per second:    1191.30 [#/sec] (mean)
Time per request:       83.942 [ms] (mean)
Time per request:       0.839 [ms] (mean, across all concurrent requests)
Transfer rate:          527.01 [Kbytes/sec] received

mod-php + PHP が一番速かった。