mod_perl スクリプトがサーバーをフリーズさせるのはなぜですか?
-
20-09-2019 - |
質問
Perl スクリプトをサーバー上で安定して実行できません。ここに問題があります。
スクリプトへのアクセスが 1 秒あたり 5 回を超えると、サーバーがフリーズします。そしてしばらくすると、サーバーが永久にハングアップします。SSH が応答しないため、サーバーを再起動する必要があります。
私はApacheを使用しています mod_perl
.
スクリプトは、Ubuntu 上の仮想専用サーバーでホストされます。SSH経由で操作しています。これらはサーバーパラメーションCPUです。400 MHz RAM:256MB
スクリプトの最大実行時間は 200 ミリ秒です。
「top」ユーティリティを使用してサーバーの負荷を監視しました。問題は表示されません。これは、1 秒あたり 5 つのスクリプトをロードしているときの CPU 統計です。
Cpu(s): 12.1%us, 0.6%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 87.2%st
スクリプトを問題なく動作させるにはどのようなオプションが必要ですか?
これは次の結果です ps aux | fgrep perl
ロードの瞬間:
ps aux | fgrep perl www-data 2925 0.3 6.5 45520 17064 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2926 0.2 6.5 45520 17068 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2927 0.4 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2928 0.3 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2929 0.2 6.5 45676 17060 ? R 17:00 0:01 /var/www/perl/loa -k start www-data 2931 0.4 6.5 45740 17076 ? R 17:00 0:01 /var/www/perl/loa -k start root 2968 0.0 0.2 3196 656 pts/0 R+ 17:06 0:00 fgrep perl
アップデート
ボトルネックを見つけました。私はコードの周りで DateTime モジュールを何度も使用してきました。次の DateTime モジュール メソッドは非常に遅いようです。
- 新しい()
- 今()
- セット(...)
- デルタ_ms(...)
それらを高速なアナログで置き換えるつもりです。
もう一つの懸念。mod_perl インスタンスは大量のメモリを消費します。そして、その理由はわかりません。モジュールをインポートしない単純な Perl スクリプトを実行しようとしました。Apacheの再起動直後に実行します。このスクリプトは 37M のメモリを必要とします。なぜそれが起こるのでしょうか?mod_perl が余分なメモリを使用しないように強制する方法をご存知ですか?
mod_perl サポートのない通常の Perl スクリプトは 3 ~ 5M のメモリを必要とします。
みなさん、本当に助けてくれてありがとう。こんなに素晴らしい反応が返ってくるとは予想していませんでした。
更新 2
もう一つ事実を発見しました。5 秒間待機するだけの簡単な Perl スクリプトを作成しました。
#!/usr/bin/perl
use CGI;
my $query= new CGI;
my $content = "5 second delay...\n";
$query->header(
'-Content-type' => "text/plain",
'-Content-Length' => length($content)
);
print $content;
sleep(5);
次に、これらのスクリプトを同時に多数生成します。最上位ユーティリティのステルス時間 (st) は 0% から 80% に跳ね上がり、スクリプトが完了するまで高いままです。
この負荷はどこから来るのでしょうか?
また、すでに述べたように、各 Perl インスタンスは 36M のメモリを必要とします。
解決
あなたの番号から top
VM の外部の他のプロセスが CPU をスロットルしていることを示しているようです。最後の数字に注目してください。 87.2%st, これは、VM に実行したい機能があるにもかかわらず、CPU 時間の約 87% がハイパーバイザーによって VM の外部のタスクに割り当てられていることを示します。これがあなたの問題に関係しているかどうかは、判断が難しいです。
が提案したようにサーバーをアップグレードするだけでなく、 くつろぐ, で提案されている永続的なプロセス環境を使用します。 ズール, 、プロセスが CPU にまったく依存しておらず、ネットワークやディスク アクセスなどの IO に依存している、またはメモリに依存している可能性があります。スクリプトが呼び出されたときに実際にどのような動作をするかについては、詳細がなければ何とも言えません。
編集: メモリ使用量に関する情報を含む更新された質問は、各プロセスがそれ自体に 45M の RAM を必要としており、さらに 17M を共有していることが明らかになりました。たった 5 つまたは 6 つのプロセスが実行されているだけで、利用可能な RAM の量を超えてしまいます。これはバニラの Perl スクリプトが使用するには十分な量のメモリですが、これをどうしているのでしょうか?
他のヒント
これは非常に大規模なサーバーではありません。それは単にそれがひざまずくなりPerlインタープリタを産卵していませんか? (私は喜んで1メガバイト以上であると仮定している)perlのロード5回目はあまりにも尋ねることがあります。
もちろん、それがキャッシュされるべき、それはまだ実行できるようになる前に初期化が必要になります。
今日の標準からすると、サーバーの仕様はそれほど印象的ではありませんが、私は同様のハードウェアでかなり複雑なものを同時に実行しました。ただし、私は非常に必要最低限の FreeBSD 設定を使用し、必要なものだけを実行しました。(ArchLinux を使用して達成できることと同様です)。多くのカスタム構成を行わず、その仕様に対して重すぎる可能性がある Ubuntu のデフォルトを受け入れたのではないかと思います。
現在、Linode 360 を試していますが、パフォーマンスは問題ありません。
さて、これはすべて明白なことを述べることを目的としています。あなたが私たちと共有していない情報が必要です。Web サーバーの構成、スクリプト + インタープリターのメモリ使用量、開いているファイルの数など。問題が発生する最小のスクリプトを提供するか、より多くの情報を提供してください。
アップデート: あなたが使っているのを見たら、 mod_perl
:1) スクリプトに必要なすべてのライブラリがサーバーの起動時にプリロードされていることを確認しましたか?2) 何か得ていますか variable won't stay shared
ログ内のメッセージ?3) 読みましたか mod_perlのパフォーマンス? (第10章:記憶の共有 特に関連性があるかもしれません)。
一般に、Apache サーバーの開始時に共通ライブラリをプリロードする必要があります。非常に単純化した経験則として、より多くのものが共有されたままであればあるほど、サーバーからより多くの情報を得ることができます。見る スタートアップファイル で 実践的なmod_perl.
さらに、サーバーあたり 35MB は少し多いと思います。Apache 構成から不要なモジュールを削除すれば、この量を削減できると思います。ただし、たとえそれができなかったとしても、たとえば 35MB をすべて共有し、さらに最大子プロセスが 50MB であれば、一度に約 20 のクライアントに対応できるはずです。
あなたがテストしているスクリプトに気づきました。実際にプリロードしてみてください CGI
サーバーの起動時に次の行を追加します startup.pl
:
use strict;
use warnings;
use CGI();
次に、そのスクリプトを次のように変更します。
#!/usr/bin/perl
use strict;
use warnings;
use CGI ();
$| = 1;
handle_request();
sub handle_request {
my $cgi = CGI->new;
my $content = "5 second delay...\n";
print $cgi->header('text/plain'), $content;
sleep(5);
}
元のスクリプトではヘッダーを送信していないことに注意してください (私は、 CGI
実例 $query
それで私はそれも自由に変更しました)。こちらも参照 Perl リファレンス.
その後、メモリ使用量を報告します。
最後に、なぜ5秒寝ているのですか?私の知る限り、Apache のスクリプトのデフォルトのタイムアウトは 3 秒です。
スクリプトがインターフェースのどのような種類を使用していますか?あなたは何度も何度もperl
実行可能ファイルを実行しないことができれば、あなたは確かにのFastCGIを使用することにより、たとえば、より良いパフォーマンスを得るだろうのます。