7

さまざまな Perl スクリプト (サーバー サイド インクルード) が、Web サイト上の多くの機能を備えた Perl モジュールを呼び出しています。 編集: スクリプトはuse libを使用して、フォルダーからライブラリを参照しています。繁忙期には、スクリプト (ライブラリーではない) がゾンビになり、サーバーに過負荷がかかります。

サーバーには次のリストが表示されます。

319 ?        Z      0:00 [scriptname1.pl] <defunct>    
320 ?        Z      0:00 [scriptname2.pl] <defunct>    
321 ?        Z      0:00 [scriptname3.pl] <defunct>

私はそれぞれ何百ものインスタンスを持っています。

編集: SSI ディレクティブを除いて、fork、system、または exec を使用していません。

<!--#exec cgi="/cgi-bin/scriptname.pl"-->

私の知る限り、この場合、httpd 自体がプロセスの所有者になります。MaxRequestPerChild が 0 に設定されているため、子プロセスが終了する前に親プロセスが終了することはありません。

これまでのところ、一部のスクリプトを一時的に中断することで、サーバーが機能していないプロセスに対処し、倒壊するのを防ぐことができると考えていましたが、ゾンビ プロセスがまだ形成されていることは疑いの余地がありません。どうやらgbaconは、サーバーが負荷に対処できないという彼の理論に最も近いようです。

httpd がこれらのプロセスを放棄する原因は何ですか? これらの発生を防ぐためのベストプラクティスはありますか?

ありがとう

回答: ポイントはロブに行きます。彼が言うように、SSI を生成する CGI スクリプトはそれらの SSI を処理しません。SSI の評価は、Apache 1.3 要求サイクルで CGI を実行する前に行われます。これは Apache 2.0 以降で修正され、CGI が SSI コマンドを生成できるようになりました。

Apache 1.3 で実行していたため、ページ ビューごとに SSI が無効なプロセスに変わりました。サーバーはそれらをクリアしようとしましたが、実行中のタスクで忙しすぎて成功できませんでした。その結果、サーバーがダウンし、応答しなくなりました。短期的な解決策として、すべての SSI を見直し、一部のプロセスをクライアント側に移動して、サーバー リソースを解放し、クリーンアップする時間を確保しました。その後、Apache 2.2 にアップグレードしました。

4

3 に答える 3

7

ベストプラクティスよりもバンドエイドの方が多いですが、単純な方法でうまくいく場合もあります

$SIG{CHLD} = "IGNORE";

perlipcのドキュメントによると

ほとんどの Unix プラットフォームでは、CHLD( としても知られるCLD) シグナルは、 の値に関して特別な動作をします'IGNORE'。このようなプラットフォームで を設定$SIG{CHLD}すると、親プロセスがその子プロセスで失敗したときにゾンビ プロセスを作成しないという効果があります (つまり、子プロセスは自動的にリープされます)。set to を指定して呼び出すと、通常、そのようなプラットフォームでは -1 が返されます。'IGNORE'wait()wait()$SIG{CHLD}'IGNORE'

子プロセスの終了ステータスが気になる場合は、waitまたはを呼び出してそれらを収集する (一般に「リーピング」と呼ばれます) 必要がありますwaitpid。不気味な名前にもかかわらず、ゾンビは、終了したもののステータスがまだ取得されていない単なる子プロセスです。

Perl プログラム自体がゾンビになる子プロセスである場合、その親 (コードを fork して忘れているもの) は自分でクリーンアップする必要があります。プロセスがゾンビになるのを止めることはできません。

于 2010-01-07T17:14:34.607 に答える
2

I just saw your comment that you are running Apache 1.3 and that may be associated with your problem.

SSI's can run CGI's. But CGI scripts that generate SSI's will not have those SSI's handled. The evaluation of SSI's happens before the running of CGI's in the Apache 1.3 request cycle. This was fixed with Apache 2.0 and later so that CGI's can generate SSI commands.

As I'd suggested above, try running your scripts on their own and have a look at the output. Are they generating SSI's?

Edit: Have you tried launching a trivial Perl CGI script to simply printout a Hello World type HTTP response?

Then if this works add a trivial SSI directives such as

<!--#printenv -->

and see what happens.

Edit 2: Just realised what is probably happening. Zombies occur when a child process exits and isn't reaped. These processes are hanging around and slowly using up resources within the process table. A process without a parent is an orphaned process.

Are you forking off processes within your Perl script? If so, have you added a waitpid() call to the parent?

Have you also got the correct exit within the script?

CORE::exit(0);
于 2010-01-07T21:25:57.047 に答える
0

自分ですべてのビットを持っているので、個々のスクリプトをコマンド ラインから一度に 1 つずつ実行して、ハングしているスクリプトを見つけられるかどうかを確認することをお勧めします。

ps リストには、実行中の特定のスクリプトのインスタンス数が異常に多く表示されますか?

mod_perl を使用して CGI を実行していますか?

編集: SSI に関するあなたのコメントを見ました。SSI ディレクティブは Perl スクリプト自体を実行できることを忘れないでください。CGI が何を実行しようとしているのか見てみましょう。

それらはさらに別のサーバーまたはサービスに依存していますか?

于 2010-01-07T18:25:31.467 に答える