web-dev-qa-db-ja.com

Tomcatリクエストのタイムアウト

私のWebアプリケーションには、20秒以上続くリクエストがいくつかあります。しかし、状況によっては、コードが無限ループまたはサーバーをスローダウンさせる同様の何かを引き起こす可能性があります。

サーバー側で60秒間リクエストタイムアウトを設定したい。これはTomcatに実装されていますか?

ありがとう、ホラティウ

41
Horatiu Jeflea

Tomcat 7では、 StuckThreadDetectionValve を追加できます。これにより、「スタック」しているスレッドを識別できます。検出を行いたいアプリケーションのContext要素でバルブを設定できます:

<Context ...>
  ...
  <Valve 
    className="org.Apache.catalina.valves.StuckThreadDetectionValve"
    threshold="60" />
  ...
</Context>

これにより、60秒より長い時間がかかるスレッドのWARNエントリがTomcatログに書き込まれます。これにより、アプリケーションに障害が発生したため、アプリケーションを識別して禁止できます。

ソースコード に基づいて、スレッドを停止しようとする独自のValveを作成できる場合がありますが、これはスレッドプールに影響を及ぼし、 信頼できる方法はありません でスレッドを停止するJavaそのスレッドの協力なしで...

44
beny23

リクエストの実行が長くなりすぎないようにする場合、Tomcatでタイムアウトを設定しても役に立ちません。 Chrisが言うように、Tomcatのグローバルタイムアウト値を設定できます。ただし、 The Apache Tomcat Connector-Generic HowTo Timeouts から、返信タイムアウトセクションを参照してください:

JKは、要求の応答にタイムアウトを使用することもできます。このタイムアウトは、応答の完全な処理時間を測定しません。代わりに、連続する応答パケット間の許容時間を制御します。

ほとんどの場合、これが実際に必要なものです。たとえば、長時間実行されるダウンロードを検討してください。ダウンロードは数分間続く可能性があるため、効果的なグローバル応答タイムアウトを設定することはできません。ただし、ほとんどのアプリケーションでは、応答を返す前に処理時間が制限されています。これらのアプリケーションでは、明示的な応答タイムアウトを設定できます。応答タイムアウトと調和しないアプリケーションは、バッチタイプのアプリケーション、データウェアハウス、および長い処理時間を観測することが予想されるレポートアプリケーションです。

応答タイムアウトが発生したためにJKが応答の待機を中止した場合、バックエンドで処理を停止する方法はありません。 Webサーバーの処理リソースを解放しますが、リクエストはバックエンドで実行され続けます-応答タイムアウトが発生すると結果を返送する方法はありません。

そのため、Tomcatは、サーブレットがタイムアウト内に応答しなかったことを検出し、ユーザーに応答を返しますが、実行中のスレッドを停止しません。あなたがやりたいことを達成できるとは思いません。

22
Matthew Farwell

Server.xmlでデフォルトのタイムアウトを設定できます

<Connector URIEncoding="UTF-8" 
    acceptCount="100" 
    connectionTimeout="20000" 
    disableUploadTimeout="true" 
    enableLookups="false" 
    maxHttpHeaderSize="8192" 
    maxSpareThreads="75" 
    maxThreads="150" 
    minSpareThreads="25" 
    port="7777" 
    redirectPort="8443"/>
11
Chris

この記事では、サーバーレベルでのタイムアウトの設定について説明します。 http://www.coderanch.com/t/364207/Servlets/Java/Servlet-Timeout-two-ways

アプリケーションが無限ループに入る原因は何ですか?他のリソースへの接続を開いている場合、それらの接続にタイムアウトを設定し、タイムアウトが発生したときに適切な応答を送信することができます。

1
thcricketfan

私のような上記のソリューションがどれも好きではない人は、タイマーを自分で実装し、ランタイム例外をスローしてリクエストの実行を停止することができます。以下のようなもの:

                  try 
                 {
                     timer.schedule(new TimerTask() {
                       @Override
                       public void run() {
                         timer.cancel();
                       }
                     }, /* specify time of the requst */ 1000);
                 }
                 catch(Exception e)
                 {
                   throw new RuntimeException("the request is taking longer than usual");
                 }

またはできればJava guava timeLimiter here

0
george