Webサーバー側でタイムアウト後にプロセスを停止させる方法

2010年2月14日

タイムアウトという現象をよく自分のブラウザで見ることがあると思いますが、 これはブラウザ側で通信が時間内に完了しなかったために発生しているものであって、 サーバー側からエラーを送出しているわけではありません。
これをきちんと理解しておかないと、100MBのファイルをサーバーにCGI経由でアップロード させようとしたらブラウザがタイムアウトとなってできません。。。 ということになってしまいます。

ですので、よくタイムアウトを理解する必要があります。
例えば、入力によってはものすごい膨大な計算をしなければならないCGIプログラムがあったと します。その時間が10分程度だったとしましょう。そうすると、何も対策をしていなければ 以下のようになります。

(1)ブラウザからCGIにアクセス。
(2)サーバ側でCGIプロセス起動し、計算開始。
(3)ブラウザ側でタイムアウト時間(Firefoxだと1分)を迎えると、
   ブラウザがタイムアウト画面を出してTCPコネクションを切断。
(4)その間もサーバ側では計算プロセスが実行中。。。
(5)サーバ側でタイムアウト時間を迎える(Apacheだと5分)と、
   Apache側からプロセスに対して強制終了シグナルが送出され、
   プロセス終了。


上記アクセスが複数クライアントから同時にきたらどうなるでしょう?
サーバ側ではただでさえCPU占有率が100%なのに、また計算プロセスが 立ち上がり、それがどんどん貯まってゆくのです。

従って上記のようなアプリケーションサーバでは特にタイムアウト処理について 考えていかなければなりません。サーバ側タイムアウトはApacheならばhttp.confの Timeoutを設定することで時間を変更することができますが、ブラウザによって タイムアウト時間は異なりますし、何よりプロセスが強制終了されますので、 データ変更中に終了されたりするとこれがシステム不調につながる可能性があり、 不十分です。

Apache側からタイムアウト時に送出されるシグナルはSIGTERMです。
SIGTERMはプロセス終了に使いますが、SIGKILLと異なる点は、プロセスが当該シグナル を受け取る余地が残されているところにあります。
従って、CGIプログラム側でSIGTERMプロセスに対するハンドラを実装することで 解決できます。

このようなケースに遭遇することはよくありますので、その際は上記のことを考えて システム設計しましょう。