Open hysryt opened 3 years ago
$ apt update
$ apt install apache2 php-cgi
$ a2dismod php7.4
$ a2enmod cgi
$ cp /usr/bin/php-cgi /var/www/html
$ service apache2 restart
/var/www/html/test.php
<?php
echo 'Hello';
?>
/etc/apache/apache.conf
AddHandler php-script .php
ScriptAlias /php-cgi "/var/www/html/php-cgi"
Action php-script /php-cgi
<Directory /var/www/>
Options +ExecCGI
</Directory>
AddHandler
で .php ファイルに php-script
ハンドラを設定。
ScriptAlias
で /var/www/html/php-cgi
に cgi-script
ハンドラを設定。
Action
で php-script
ハンドラへのリクエスト時は /php-cgi
をCGIとして実行するように設定。
Options +ExecCGI
で /var/www/
内のファイルをCGIとして実行できるように設定。
php-cgi を使う場合は Action ディレクティブなどを使って REDIRECT_STATUS 変数を渡す必要があるとのこと https://msakamoto-sf-2007-to-2011.hatenadiary.jp/entry/20080802/1217662203 (header関数などを使用する場合は php ではなく php-cgi を使う必要がある)
セキュリティ上の理由から php-cgi のラッパーを作成する場合もある。 https://blog.tokumaru.org/2012/05/php-cgi-remote-scripting-cve-2012-1823.html (PHP7.4で試してみた感じ現在はphp-cgi側で対応されている?) いずれにせよ現在ではCGIを使うことはまずなく、FastCGIかモジュールのどちらかで動作させることが多い。
https://www.php.net/manual/ja/install.fpm.php
$ apt update
$ apt install apach2 php php-fpm
$ a2dismod php7.4
$ a2enmod proxy_fcgi
$ a2enconf php7.4-fpm
$ service apache2 start
$ service php7.4-fpm start
apache と php-fpm の通信方法にはUNIXソケットとTCPの2種類がある。 デフォルトはUNIXソケット(/run/php/php7.4-fpm.sockになっていた)
/etc/php/7.4/fpm/pool.d/www.conf(デフォルトの設定)
[www]
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php-fpmの設定値について https://www.php.net/manual/ja/install.fpm.configuration.php https://qiita.com/r_sui/items/29ec160c4e830c138132 https://hackers-high.com/linux/php-fpm-config/
$ apt install php-fpm
$ which php-fpm7.4
/usr/sbin/php-fpm7.4
$ service php7.4-fpm start
php-fpm はインストール時にサービスとして登録されるため service コマンドで起動できる。
% ab -n 10000 -c 100 http://localhost:8080/test.php
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Apache/2.4.46
Server Hostname: localhost
Server Port: 8080
Document Path: /test.php
Document Length: 5 bytes
Concurrency Level: 100
Time taken for tests: 9.438 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 1750000 bytes
HTML transferred: 50000 bytes
Requests per second: 1059.58 [#/sec] (mean)
Time per request: 94.377 [ms] (mean)
Time per request: 0.944 [ms] (mean, across all concurrent requests)
Transfer rate: 181.08 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 11 87.5 2 1818
Processing: 7 83 157.2 66 1853
Waiting: 4 75 129.8 63 1820
Total: 8 94 180.2 72 1894
Percentage of the requests served within a certain time (ms)
50% 72
66% 77
75% 81
80% 83
90% 91
95% 106
98% 344
99% 1830
100% 1894 (longest request)
途中から遅くなるのはプロセスが少ないせい?
% ab -n 10000 -c 100 http://localhost:8080/test.php
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Apache/2.4.46
Server Hostname: localhost
Server Port: 8080
Document Path: /test.php
Document Length: 5 bytes
Concurrency Level: 100
Time taken for tests: 6.861 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 1710000 bytes
HTML transferred: 50000 bytes
Requests per second: 1457.54 [#/sec] (mean)
Time per request: 68.609 [ms] (mean)
Time per request: 0.686 [ms] (mean, across all concurrent requests)
Transfer rate: 243.40 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 9 11.9 2 162
Processing: 5 59 23.5 56 240
Waiting: 3 56 24.2 53 240
Total: 7 68 23.3 64 240
Percentage of the requests served within a certain time (ms)
50% 64
66% 70
75% 74
80% 77
90% 84
95% 91
98% 172
99% 216
100% 240 (longest request)
https://qiita.com/mpyw/items/c69da9589e72ceac470c https://qiita.com/tanakahisateru/items/e3e24f3825c4ba0c60e6 https://www.moxio.com/blog/34/best-practices-for-php-exception-handling
用語 | 説明 |
---|---|
致命的なエラー | E_ERRORに該当するエラー。Fatal Errorともいう。PHP7以降ではErrorを投げる。 |
警告 | E_WARNINGに該当するエラー。Warning。 |
Error | Errorクラス。内部エラー。catch句でキャッチできる。 https://www.php.net/manual/ja/function.set-error-handler.php コンパイルエラーのようなものなので発生した場合はcatchして処理するのではなくコードを修正するべき。 本番環境では発生してはならない。 |
Exception | Exceptionクラス。ユーザー例外。catch句でキャッチできる。 https://www.php.net/manual/ja/class.exception.php LogicExceptionとRuntimeExceptionの分類が難しいもの? |
ErrorException | E_ERROR,E_WORNINGなどを表すための例外。 |
LogicException | Exceptionクラスのサブクラス。 Errorに近い。 コードの不備による例外。Errorと同じように、発生した場合はcatchして処理するのではなくコードを修正するべき。 |
RuntimeException | Exceptionクラスのサブクラス。 実行時の例外。(ユーザーからの入力やネットワーク接続エラーなど) |
https://www.php.net/manual/ja/function.set-error-handler.php
E_NOTICE、E_WARNING、E_USER_NOTICE、E_RECOVERABLE_ERROR をハンドリングする関数を設定できる。 ハンドラーの中で ErrorException を投げることでキャッチ可能なExceptionに変換できる。
E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNINGはハンドリングできない。
set_error_handler(function($errno, $errstr, $errfile, $errline){
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});
try {
file_get_contents('nonexistent file'); // ファイルが存在しないため E_WARNING 発生
} catch (ErrorException $e) {
var_dump($e);
}
Exception は LogicException と RuntimeException に大別できる。 ロジック上に問題のあるもの(修正が必要なもの)はLogicException、それ以外はRuntimeException。 発生時点で判別が難しいものはException?
オブジェクトのシリアライズには serialize()
、シリアライズかされたデータからオブジェクトを復元するには unserialize()
を使用する。
class Test() {}
$test = new Test();
$serialized = serialize($test); // シリアライズ
$test = unserliazed($serialized); // アンシリアライズ
シリアライズ化されたデータはnullバイトを含むバリナリデータとなる。 そのためデータベースに保存する際はTEXT型ではなくBLOB型で保存する必要がある。
ファイルの自動読み込み。
spl_autoload_register()
に読み込み用の関数を登録することで、必要になったタイミングで自動でファイルを読み込むことができる。
名前空間が Test から始まるクラスを、autoload.php
と同じ階層からオートロードする例。
spl_autoload_register(function(string $class) {
$targetNamespace = 'Test\\';
// 管轄外の名前空間のものは無視
if (!(strpos($class, $targetNamespace) === 0)) {
return;
}
$includePath = __DIR__;
$classPath = substr($class, strlen($targetNamespace));
$filePath = str_replace('\\', DIRECTORY_SEPARATOR, $classPath) . '.php';
$fileFullPath = $includePath . DIRECTORY_SEPARATOR . $filePath;
if (is_file($fileFullPath) && is_readable($fileFullPath)) {
require_once($fileFullPath);
}
});
CLI/CGI
PHPにはCLI用とCGI用が存在する。 CGI用PHPは出力にHTTPヘッダーが付けられる。 https://www.php.net/manual/ja/features.commandline.differences.php
CGI用PHPはFastCGIに対応している。 ただしFastCGIを使う場合はphp-fpmを使った方が設定が楽? (php-fpmは内部的にCGI用PHPを使用している)
HomebrewでPHPをインストールすると
php
コマンドがCLI用PHP、php-cgi
コマンドがCGI用PHPとなる。参考 https://wiki.bit-hive.com/tomizoo/pg/PHP%20CLI%2FCGI%20SAPI https://www.php.net/manual/ja/features.commandline.php https://server-setting.info/centos/php-fpm-php-cgi.html