web-dev-qa-db-ja.com

ランダムな502ゲートウェイエラーを引き起こしているNginx / PHP-FPMボトルネックを見つける

私はかなり忙しいインターネットサイトで働いており、トラフィックが非常に急増することがよくあります。これらのスパイクの間、毎秒数百ページが要求され、これによりランダムな502ゲートウェイエラーが発生します。

ここで、Nginx(1.0.10)とPHP-FPMを、16コアCPUと24GBのDDR3RAMを搭載した4x SAS 15kドライブ(raid10)を搭載したマシンで実行します。最新のXcacheバージョン。DBは別のマシンにありますが、このマシンの負荷は非常に低く、問題はありません。

通常の負荷では、すべてが完全に実行され、システム負荷は1未満であり、PHP-FPMステータスレポートには、一度に10を超えるアクティブなプロセスが表示されることはありません。まだ約10GBのラムがまだ利用可能です。通常の負荷では、マシンは1秒あたり約100ページビューを処理します。

この問題は、トラフィックの急増が到着し、1秒あたり数百のページビューがマシンから要求されたときに発生します。 FPMのステータスレポートには最大50のアクティブなプロセスが表示されますが、それでも構成した最大接続数300をはるかに下回っています。これらのスパイクの間、Nginxステータスは、通常の平均である1000ではなく、最大5000のアクティブな接続を報告します。

OS情報:CentOSリリース5.7(最終版)

CPU:Intel(R)Xeon(R)CPU E5620 @ 2.40GH(16コア)

php-fpm.conf

daemonize = yes
listen = /tmp/fpm.sock
pm = static
pm.max_children = 300
pm.max_requests = 1000

Rlimit_filesを設定していません。私が知る限り、設定していない場合はシステムのデフォルトを使用する必要があるためです。

fastcgi_params(標準ファイルに追加された値のみ)

fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;

fastcgi_pass            unix:/tmp/fpm.sock;

nginx.conf

worker_processes        8;
worker_connections      16384;
sendfile                on;
tcp_nopush              on;
keepalive_timeout       4;

NginxはUnixソケットを介してFPMに接続します。

sysctl.conf

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 1
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.eth0.rp_filter=1
net.ipv4.conf.lo.rp_filter=1
net.ipv4.ip_conntrack_max = 100000

limits.conf

* soft nofile 65536
* hard nofile 65536

これらは、次のコマンドの結果です。

ulimit -n
65536

ulimit -Sn
65536

ulimit -Hn
65536

cat /proc/sys/fs/file-max
2390143

質問: PHP-FPMの接続が不足していない場合でも、負荷は低く、RAMが利用可能ですが、どのボトルネックがこれらのランダムを引き起こしている可能性がありますか?高トラフィック時の502ゲートウェイエラー?

注:デフォルトでは、このマシンのulimitは1024でした。これは、65536に変更したため、実稼働マシンであり、ダウンタイムが長すぎるため、マシンを完全に再起動していません。

3
Mr.Boon

公式の推奨事項:worker_processes =コア数CPU

セットする worker_processes 16;

1
Artur Zh

HAProxyやnginxなどのロードバランサーからの散発的な502エラーは、通常、LBとWebサーバーの間の途中で何かが切断されることによって発生します。

GDBを介してWebサーバーの1つ、またはそのテストコピーを実行し、テストトラフィックの生成時にセグメンテーション違反が発生するかどうかを確認します(トラフィックのシミュレーションにはabまたはjMeterなどを使用します)。

私は最近、非常によく似たシナリオ/問題を解決しなければなりませんでした。私はそこで私を助けてくれたかなり包括的な監視をしていたので、問題を引き起こしているリソースなどを除外しました。結局、502エラーがロードバランサーの背後にあるWebサーバーから発生し、LBに無効な(この場合は空の)HTTP応答を返していることがわかりました。

Webサーバーの1つを取得し、Webサーバーを停止してから、gdbを介して再起動し、サイトを参照しました。最終的に、クリックして回った後、セグメンテーション違反が発生し、これにより502エラーが表示されました。 GDBからバックトレースを取得し、バグとしてPHPチームに送信しましたが、唯一の修正は、PHPバグを回避するためにディストリビューションを切り替えることでした。それはそこにありました。

セグメンテーション違反により、Webサーバーが無効なコンテンツをLBに送信し、Webサーバーが「フローの途中」で消えたため、LBは502エラーを表示していました。

これがあなたの質問に直接答えないことは知っていますが、それは探し始める場所です。セグメンテーション違反が発生した場合は、GDBからスタックトレースを取得できます。逆方向に作業して、セグメンテーション違反の原因となっている関数を見つけることができます。

2
SimonJGreen