web-dev-qa-db-ja.com

PHP5-FPMがランダムに大量のCPUを消費し始める

さらにデバッグする方法がわからない、本当に奇妙な問題に遭遇しました。 NGINX + PHP5-FPM + APC Amazon Ubuntuインスタンスがあり、そこにインストールされているウェブサイトは複雑ですPHPフレームワーク。問題をデバッグしようとしている間、フローを減らしましたこれには、多くの大きなクラスが含まれ、メインオブジェクトが作成され、セッションが開始され、configの配列がmemcachedから取得され、XMLファイルがmemcachedから取得され、HTMLテンプレートが含まれ、出力がクライアントに送信されます。

次に、http_loadツールを使用して、1秒あたり20リクエストの負荷をウェブサイトに加えます:http_load -timeout 10 -rate 20 -fetches 10000 ./urls.txt

次に何が起こるかは奇妙です。 topは、それぞれが数%のCPUを使用して生成された多数のphp5-fpmプロセスを示し、次のようにすべてがスムーズに実行されます。

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28440 www-data 20 0 67352 10m 5372 S 4.3 1.8 0:20.33 php5-fpm
28431 www-data 20 0 67608 10m 5304 S 3.3 1.8 0:16.77 php5-fpm
28444 www-data 20 0 67352 10m 5372 S 3.3 1.8 0:17.17 php5-fpm
28445 www-data 20 0 67352 10m 5372 S 3.0 1.8 0:16.83 php5-fpm
28422 www-data 20 0 67608 10m 5292 S 2.3 1.8 0:18.99 php5-fpm
28424 www-data 20 0 67352 10m 5368 S 2.0 1.8 0:16.59 php5-fpm
28438 www-data 20 0 67608 10m 5304 S 2.0 1.8 0:17.91 php5-fpm
28439 www-data 20 0 67608 10m 5304 S 2.0 1.8 0:23.34 php5-fpm
28423 www-data 20 0 67608 10m 5292 S 1.7 1.8 0:20.02 php5-fpm
28430 www-data 20 0 67608 10m 5300 S 1.7 1.8 0:15.77 php5-fpm
28433 www-data 20 0 67352 10m 5372 S 1.7 1.8 0:17.08 php5-fpm
28434 www-data 20 0 67608 10m 5292 S 1.7 1.8 0:18.56 php5-fpm
20648 memcache 20 0 51568 8192 708 S 1.3 1.3 2:51.06 memcached
28420 www-data 20 0 69876 13m 6300 S 1.3 2.3 0:20.89 php5-fpm
28421 www-data 20 0 67608 10m 5300 S 1.3 1.8 0:21.19 php5-fpm
28429 www-data 20 0 9524 2260 992 S 1.3 0.4 0:11.68 nginx
28435 www-data 20 0 67608 10m 5304 S 1.3 1.8 0:18.58 php5-fpm
28437 www-data 20 0 67352 10m 5372 S 1.3 1.8 0:17.87 php5-fpm
28441 www-data 20 0 67608 10m 5292 S 1.3 1.8 0:20.75 php5-fpm

次に、1秒から数分の間になる可能性があるしばらくすると、いくつか(通常は2つ)のphp5-fpmプロセスが突然すべてのCPUを消費します。

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28436 www-data 20 0 67608 10m 5304 R 48.5 1.8 0:23.68 php5-fpm
28548 www-data 20 0 67608 10m 5276 R 45.2 1.7 0:07.62 php5-fpm
28434 www-data 20 0 67608 10m 5292 R 2.0 1.8 0:23.28 php5-fpm
28439 www-data 20 0 67608 10m 5304 R 2.0 1.8 0:26.63 php5-fpm

この時点ですべてがスタックし、すべての新しいHTTPリクエストがタイムアウトします。 http_loadツールを停止すると、php5-fpmが数分間ハングします。興味深いことに、私がやれば十分ですphp5-fpm stop、php5-fpmプロセスは表示されなくなりますが、ファイルシステムを使用するコマンドは実行に問題があります。例えば。 ssh経由でファイルをダウンロードしようとすると、topに次のように表示され、実際のダウンロードを開始するまでに数分かかります。

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3298 sshd 20 0 7032 876 416 R 75.2 0.1 0:04.52 sshd
3297 sshd 20 0 7032 876 416 R 24.9 0.1 0:04.49 sshd

PHPエラーログには通常、次のようになります。

[05-Dec-2012 20:31:39] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 58 total children
[05-Dec-2012 20:32:08] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 0 idle, and 66 total children

Nginxエラーログには次のエントリが殺到しています。

2012/12/05 20:31:36 [error] 4800#0: *5559 connect() to unix:/dev/shm/php-fpm-www.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: ..., server: ec2-....compute-1.amazonaws.com, request: "GET /usa/index.php?page=contact_us HTTP/1.0", upstream: "fastcgi://unix:/dev/shm/php-fpm-www.sock:", Host: "ec2-....compute-1.amazonaws.com"

PHP-FPMの遅いログは興味深いものを何も表示せず、スワッピングは発生せず、問題について他の興味深い事実を収集することができませんでした。私は設定ファイルの変更を何度も繰り返してきましたが、最新のものは

nginx.conf: http://Pastebin.com/uaD56hJF

pool.d/www.conf: http://Pastebin.com/mFeeUULC

===更新1 ===

サイトの設定: http://Pastebin.com/qvinVNhB

===更新2 ===

また、dmesgがこのようなエラーを報告することもわかりました

[6483131.164331] php5-fpm[28687]: segfault at b6ec8ff4 ip b78c3c32 sp bff551f0 error 4 in ld-2.13.so[b78b5000+1c000]

===更新3 ===

考えられるハードウェアの問題を排除するために、念のために新しいAmazon EC2マイクロインスタンスを用意しました。また、私は現在php-fastcgiを使用して、可能なfpmバグを除外しています。他の違いはわずかですが、変更点はUbuntu-> Debianだけだと思います。サーバーがmax_execution_time秒後にわずかに回復し、その後再び急上昇することを除いて、同じ問題が依然として発生します。

別のtest.phpで遊んでみましたが、同じ問題かどうかはわかりませんが、少なくともtopでは同じに見えます。 test.phpを作成し、フレームワークに属する多数のライブラリを含めました。ライブラリは、クラスを定義すること、またはクラスを定義する他のライブラリを含めること以外は何もしません。私はAPCで確認しましたが、これはすべてAPCによって正常に提供されています。私は毎秒200リクエストでtest.phpに圧力をかけ始め、しばらくすると同じことが起こりました。それを除けば、「開いているファイルが多すぎる」というエラーが出ました。ただし、常に発生するわけではありません。時々、エラーを出力せずにタイムアウトし始め、いくつかのphpプロセスがスタックしてすべてのCPUを消費します。私は少し遊んだだけですが、ここには相関関係があると思います。含まれているライブラリの数を制御するか、リクエスト数/秒のレートを少し変えることで、CPUスパイクが発生するタイミングを制御できます。関連するOS変数を増やしましたが、問題が発生するまでには時間がかかりますが、問題はまだあります(テスト中に行うリクエストの総数のN倍の値に制限を設定していることにも注意してください)。

fs.file-max = 70000
...
*       soft    nofile   10000
*       hard    nofile  30000
...
worker_rlimit_nofile 10000;
...
(reloaded all the configs and made sure the new system vars actually took affect)

したがって、これまでに思いつくことができる次善かつ唯一の説明は、APCがメモリからファイルをプルすることになっているにもかかわらず、内部的には、常にPHP = include-sが呼び出されます。遅延して解放されるか、不幸なタイミングで同時に多くの要求が到着した場合、システムは記述子を実行し、新しく到着したHTTP要求がすぐに巨大なキューにスタックされます。なんとかしてこれをテストしてみます。

13
Eugene

ダウンタイムなしで、同様の構成のWebサイトを何ヶ月も実行しました。私はあなたの設定を見ました、そしてそれは大丈夫に見えます。そうは言っても、かなり前に設定を行いました。

pm.max_requests = 10000pm.max_requests = 500のようなより妥当な値に減らすことを検討します。これは、「X個を超えるリクエストに対して各インスタンスを使用しないこと」を意味します。 PHPエンジンのバグに関して回復力を与えるので、この数を高くしすぎないようにしてください。

本当の問題はあなたのPHPスクリプトにある可能性が高いと思います。詳細を知らなければ、言うのは難しいです。

編集:;request_terminate_timeout = 0のコメントを外して、request_terminate_timeout = 20のように設定することを検討してください。その後、スクリプトは20秒以内に完了する必要があります。ほとんどの場合、動作に変化が見られますが、サイトは引き続き稼働している可能性があります。 PHPスクリプトエラーを示します。

EDIT2:私自身のphp-fpm設定は次のとおりです:

[example.com]
listen = /var/run/sockets/example.com.socket
user = www-data
group = www-data
pm = dynamic
pm.start_servers = 5
pm.max_children = 15
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
php_flag[expose_php] = off
php_flag[short_open_tag] = on

編集3:私はあなたのnginx設定で予期しない何かを見つけましたが、それは何もかもしれません。

古いバージョンのnginxでワーカープロセスに問題を引き起こすfastcgi_ignore_client_abort on;を使用しています。私は最近のバージョンのカスタムコンパイルを実行しているので、この問題は自分では見ていません。 nginxサイトの問題の説明は次のとおりです。

1.0.2ではPOST fastcgi_ignore_client_abortがonに設定されているとリクエストが正しく処理されず、ワーカープロセスのセグメンテーション違反につながる可能性があります。fastcgi_ignore_client_abortをデフォルト(オフ)に戻すと、この問題は解決します。

10
Kevin A. Naudé

単純なトリックですが、プロセッサの使用率を最大50%削減するのに非常に便利です。php-fpm設定を編集するだけです。

pm = dynamic

それを次のように変更します。

pm = ondemand
3
Animanga

私は今、この同じ問題を経験しており、この投稿を紹介したいと思います:

PHP-FPMプロセスで実行されているスクリプトを特定する方法

PHPスクリプトの1つである必要があります。暴走したプロセスIDと、それを妨げている.phpスクリプトファイルの間にドットを接続できるかどうかを確認してください。

おかしい、これは非の打ちどころのないほど高速なサーバー上にありました。 WordPressアップグレード(プラグインまたはコア))が非常に責任があると思います。

1
Berto

私のサーバーでのPHP-FPMの動作はあなたと同じです。確かにどこかでボトルネック。
質問が判明しました:Nginx-PHP-FPM-Mysqlでボトルネックを見つける方法は?見つけるための最速の方法は、PHP-FPMでSlowlogを有効にすることです。
php-fpm.confプールに以下の行を追加し、パスが存在することを確認してください

request_slowlog_timeout = 10
slowlog = /var/log/php-fpm/slow.$pool.log

ログのバックトレースを読むと、PHP-FPMがCPUまたはタイムアウトに多くの時間を費やした理由がわかります。これが私のケースです:

[28-Dec-2018 14:56:55]  [pool laravel] pid 19061
script_filename = /public_html/index.php
[0x00007efdda4d8100] hasChildren() /public_html/laravel/vendor/symfony/Finder/Iterator/ExcludeDirectoryFilterIterator.php:75
[0x00007ffe31cd9e40] hasChildren() unknown:0
[0x00007ffe31cda200] next() unknown:0
[0x00007ffe31cda540] next() unknown:0
[0x00007ffe31cda880] next() unknown:0
[0x00007efdda4d7fa8] gc() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/FileSessionHandler.php:91
[0x00007efdda4d7e50] gc() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:159
[0x00007efdda4d7d48] collectGarbage() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:128
[0x00007efdda4d7c20] closeSession() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware.php:79
[0x00007efdda4d7ac8] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Queue.php:47
[0x00007efdda4d7930] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Guard.php:51
[0x00007efdda4d7818] handle() /public_html/laravel/vendor/stack/builder/src/Stack/StackedHttpKernel.php:23
[0x00007efdda4d76e0] handle() /public_html/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:641
[0x00007efdda4d7598] run() 
/public_html/index.php:51

バックトレースはこれらのキーワードについて言及しています:

"cookie" "session" "collectGarbage()" "laravel"

私は検索とTADAを続けます、Laravel RANDOMメソッドを使用して期限切れのセッションをクリアします。そして私の設定では、PHP SSDを使用してセッションを処理します。
セッション数が「非常に大きく」なると、これはPHP処理に多くの時間を費やした=>高CPU使用率。

多くの種類のボトルネックが存在する可能性があります。「デバッグ」したときにそれを知ることができます。

素敵な調査をしてください。

1
minhhq

私も同じ問題を抱えていました。 PHP-FPMとNGINXを再構成してみましたが、それほど遠くまで行きませんでした。私たちの1人がv8js.php( http://php.net/manual/en/book.v8js.php )を無効にし、問題を修正しました。トラブルメーカーが見つかるまで、phpモジュールを無効にすることをお勧めします。うまくいけば、それは誰かを助けます。

0
Allen