現在、Apache2サーバーをmpm-prefork
とmod_php
で、512Mリアル/ 1024Mバースト可能RAM(スワップなし)のOpenVZ VPSで実行しています。いくつかのテストを実行した後、 Apacheが取得する最大プロセスサイズは23Mであることがわかったので、MaxClients
を25に設定しました(23M x 25 = 575 MB、問題ありません)。サーバーで負荷テストを実行することにしましたが、結果に戸惑いました。
デスクトップマシンでab
を使用して、wordpressブログのメインページをリクエストしています。
24個の同時接続でab
を実行すると、すべてが正常に見えます。確かに、CPUは上がり、空きはRAMが下がり、結果はリクエストごとに約2〜3秒の応答時間になります。
しかし、25個の同時接続(サーバー制限)でab
を実行すると、Apacheは数秒後にハングします。リクエストの処理を開始してから応答を停止し、CPUが100%アイドル状態に戻り、ab
がタイムアウトします。 Apacheログは、MaxClients
に達したと述べています。
これが発生すると、Apacheは25個の実行中のプロセス(サーバーのステータスを確認するとすべて「W」になっています)でロックされたままであり、TimeOut
設定の後にのみプロセスが停止し、サーバーが再び応答を開始します(私の場合は45に設定)。
私の質問:それは予想される動作ですか?なぜApacheはMaxClients
に達したときに死ぬのですか? 24の接続で機能する場合、25で機能する必要はありません。各リクエストへの応答に残りの時間を要し、残りをキューに入れるだけです。
ab
を実行している子供が、サーバーMaxClients
への同時接続を設定するだけでWebサーバーを強制終了できるのは、ちょっと奇妙に聞こえます。
ハ!ようやく自分で問題を見つけました。それはサーバー管理よりもプログラミングに関連していますが、とにかく答えをここに置くことにしました。Googleを検索したところ、そのような問題を抱えているのは私だけではないことがわかりました(そして、Apacheがハングするため、最初の問題は問題があることです。サーバーで)。
問題はApacheではなく、私のWordpressにあります。より具体的には私のテーマで。私はLightworldと呼ばれるテーマを使用しており、ブログヘッダーへの画像の追加をサポートしています。それを可能にするために、PHPの関数getimagesize()
を使用して画像サイズをチェックします。この関数はサーバーへの別のhttp接続を開いてイメージを取得していたため、ab
からの各リクエストはPHPから内部的に別のリクエストを作成していました。私はサーバーで利用可能なすべてのスロットを使用していたため、これらのPHP=リクエストはキューに入れられましたが、ApacheはそれらのプロセスにすべてのプロセスがロックされてスロットがPHP内部リクエストを完了します。
基本的に、PHPは私のサーバーをデッドロック状態にしていました。Apacheは、これらの接続がタイムアウトして「子」リクエストを待機した後にのみ正常に動作し始めました。
この機能をテーマから削除した後、サーバーを同時接続でab
好きなだけ接続できるようになり、Apacheは期待どおりにそれらをキューに入れます。
ここで起こっているのは、接続を受け入れることができる25のスレッドがあり、26の同時要求を送信していることです。その最後のリクエストは、バックログのサイズに応じてソケットキューに置かれます。
2番目の問題は、実行中の2〜3秒かかるものはすべて、25の同時接続によって速度が低下するという応答に十分な時間がかかることです。 sleep(1)は機能するかもしれませんが、mysqlからファイルロックまたはテーブルロックを行っている場合、各並列リクエストは45秒のタイムアウトに達するまで完了する前に待機している可能性があります。
23mbは、mod_phpとモジュールがロードされているApacheプロセスでは小さく聞こえるので、アプリケーションの実行中に、これらのApacheプロセスがもう少しRAMを消費しているのを目にしているのではないかと思います。 MaxClientsとそのようなメモリを使って数学を実際に行うことはできません...少し近いですが、決してわかりません。
www-data 1495 0.1 0.9 56288 19996 ? S 15:48 0:01 /usr/sbin/Apache2 -k start
www-data 1500 0.0 0.5 49684 12436 ? D 15:48 0:00 /usr/sbin/Apache2 -k start
56Mおよび49Mプロセスの1台のマシンがあります。
別のマシン:
www-data 7767 0.1 0.1 213732 14840 ? S 14:55 0:08 /usr/sbin/Apache2 -k start
www-data 8020 0.2 0.1 212424 13660 ? S 14:57 0:08 /usr/sbin/Apache2 -k start
別のマシン:
www-data 28509 0.8 0.1 161720 10068 ? S 14:39 0:43 /usr/sbin/Apache2 -k start
www-data 28511 0.8 0.1 161932 10344 ? S 14:39 0:43 /usr/sbin/Apache2 -k start
したがって、メモリの使用量は、ロードされるモジュールなどのタスクに大きく依存します。最後の2つでは、pdoとpdo_mysqlを無効にしたのは、そのアプリケーションがそれらを使用していないためです。
本当の質問は、あなたが何をしているのですか?今日の世界では、それは永遠であり、「ブロッキング」アプリケーションと見なされます。 Apacheは通常死ぬことはありませんが、それらを処理できるようになるか、待機中の要求がタイムアウトするまで、これらのスレッドをバックログキューに残します。あなたのアプリケーションがおそらくApacheのタイムアウトを引き起こしていると思います。 phpinfo()だけを含むページで試してください。結果が同じかどうかを確認します。