web-dev-qa-db-ja.com

Spring-server.connection-timeoutが機能しない

application.propertiesファイルには...

server.port=8086
server.connection-timeout=15000

サーバーがポート8086で実行されているため、ファイルが正しくロードされていることがわかります。

アプリケーションにはRestControllerがあります

@RestController
class TestController {
    @GetMapping()
    fun getValues(): ResponseEntity<*> {
        return someLongRunningProcessPossiblyHanging()
    }
}

エンドポイントを呼び出すと、リクエストがタイムアウトすることはなく、無期限にハングするだけです。

何か不足していますか?

注: Tomcatはこのフィールドをミリ秒単位ではなく分単位で使用することも通知されました(むしろ珍しい選択IMO)。これを1分を示すserver.connection-timeout=1に設定しようとしましたが、これも機能しませんでした。

注:望まないanotherHTTPリクエストにより前のリクエストがタイムアウトし、各HTTPリクエストにタイムアウトになりすぎて、リクエストを処理するには時間がかかりすぎます。

14
series0ne

connection-timeoutは、長時間実行される要求には適用されません。サーバーがクライアントが何かを言うのを待つとき、それは最初の接続に適用されます。

Tomcatドキュメント(Spring Bootではありません)として定義接続を受け入れた後、リクエストURI行が表示されるまでこのコネクタが待機するミリ秒数[...]

設定server.connection-timeout=4000をテストするには、netcatを使用して接続しますが、HTTPリクエスト/ヘッダーは送信しません。私は得る:

$ time nc -vv localhost 1234
Connection to localhost 1234 port [tcp/*] succeeded!

real    0m4.015s
user    0m0.000s
sys     0m0.000s

代替案

1)Async

brightinventions.pl-Spring MVCスレッドプールタイムアウト :から

Spring MVCでは、非同期メソッドを使用しない限り、タイムアウトを設定する方法はありません。非同期メソッドでは、spring.mvc.async.request-timeout =を使用して、非同期リクエスト処理がタイムアウトするまでの時間(ミリ秒単位)を設定できます。

spring.mvc.async.request-timeout=4000を設定しましたが、これでブラウザでタイムアウトが発生します:

@GetMapping("/test-async")
public Callable<String> getFoobar() {
   return () -> {
      Thread.sleep(12000); //this will cause a timeout
      return "foobar";
   };
}

Spring Boot REST API-request timeout? を参照してください。

2)サーブレットフィルター

別の解決策は、サーブレットフィルターを使用することです brightinventions.pl-Spring MVCでのリクエストタイムアウト (Kotlin):

override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
    val completed = AtomicBoolean(false)
    val requestHandlingThread = Thread.currentThread()
    val timeout = timeoutsPool.schedule({
        if (completed.compareAndSet(false, true)) {
            requestHandlingThread.interrupt()
        }
    }, 5, TimeUnit.SECONDS)

    try {
        filterChain.doFilter(request, response)
        timeout.cancel(false)
    } finally {
        completed.set(true)
    }
}

3)Tomcatスタックスレッド検出バルブ?

Tomcatには スタックスレッド検出バルブ がありますが、Spring Bootを使用してプログラムで設定できるかどうかはわかりません。

公式の docs から:

server.connection-timeout =#コネクタが接続を閉じる前に別のHTTP要求を待機する時間。設定されていない場合、コネクタのコンテナ固有のデフォルトが使用されます。 -1の値を使用して、タイムアウトがない(つまり、無限)ことを示します。

別の ref も同じことを述べています。それはあなたのために働くはずです。

2
Pankaj Singhal

エンドポイントを呼び出すと、リクエストがタイムアウトすることはなく、無期限にハングするだけです。

server.connection-timeoutはリクエストのタイムアウトではありません。これは、アイドル接続、つまり、すでに要求/応答ペアがあり、サーバーが2番目の要求を待機している接続のタイムアウトです。基本的にはサーバー側の読み取りタイムアウトです。

0
user207421