Nginx および PHP-CGI (php-fpm) Web サービスを実行している Linux サーバーでシステム負荷が突然増加することがあります。top コマンドを使用して、多くの php-cgi プロセスの CPU 使用率が 100% に近いことを確認します。その後、追跡を通じて、この種の状況の発生は PHP の file_get_contents() 関数と密接に関係していることがわかりました。
大規模および中規模の Web サイトでは、HTTP プロトコルに基づく API インターフェイス呼び出しが一般的です。 PHP プログラマーは、URL の返されたコンテンツを取得するために、シンプルで便利な file_get_contents("http://example.com/") 関数を使用することを好みますが、Web サイト http://example.com/ の応答が遅い場合は、file_get_contents(. " ) は常にそこでスタックし、タイムアウトしません。
php.ini には、PHP スクリプトの最大実行時間を設定できるパラメータ max_execution_time があることはわかっていますが、php-cgi (php-fpm) では、このパラメータは有効になりません。 PHP スクリプトの最大実行時間を実際に制御できるのは、php-fpm.conf 構成ファイル内の次のパラメーターです。
The timeout (in seconds) for serving a single request after which the worker process will be terminated Should be used when 'max_execution_time' ini option does not stop script execution for some reason '0s' means 'off' |
デフォルト値は 0 秒で、PHP スクリプトの実行が継続されることを意味します。このように、すべての php-cgi プロセスが file_get_contents() 関数でスタックすると、この Nginx+PHP Web サーバーは新しい PHP リクエストを処理できなくなり、Nginx はユーザーに「502 Bad Gateway」を返します。 PHP スクリプトの最大実行時間を設定するにはこのパラメータを変更する必要がありますが、根本的な原因ではなく症状を治療するだけです。たとえば、
完全な解決策を達成するには、PHP プログラマーが file_get_contents("http://example.com/") を直接使用する習慣をなくすことができますが、それをわずかに変更し、タイムアウトを追加し、次のコードを使用します。メソッド HTTP GET リクエストを実装します。それが面倒な場合は、次のコードを自分で関数にカプセル化することもできます。
$ctx = stream_context_create(array( 'http' => array( 'timeout' => 1 //设置一个超时时间,单位为秒 ) ) ); file_get_contents("http://example.com/", 0, $ctx); ?> |
もちろん、php-cgi プロセスの CPU が 100% に達する原因はこれだけではありません。では、それが file_get_contents() 関数によるものであるかどうかを判断するにはどうすればよいでしょうか?
まず、top コマンドを使用して、CPU 使用率が高い php-cgi プロセスを表示します。
トップ - 10:34:18 724 日、21:01、3 ユーザー、負荷平均: 17.86、11.16、7.69 PID ユーザー PR NI VIRT RES SHR S %CPU %MEM TIME+ |
その中の 1 つの CPU 100% の php-cgi 処理の PID を次のコマンドで追跡します:
strace -p 10747
すると、問題の原因は file_get_contents() であると判断できます。
|