私は春ブーツWebアプリケーションを作成し、Tomcatコンテナに同じの戦争を展開しています。アプリケーションは、に接続しているmongoDB
非同期接続を使用します。私が使用していますmongodb-driver-async
そのためのライブラリを。
起動時にすべてが正常に動作します。しかし、すぐに負荷が増加すると、それはDB接続での例外次を示しています。
org.springframework.web.context.request.async.AsyncRequestTimeoutException: null
at org.springframework.web.context.request.async.TimeoutDeferredResultProcessingInterceptor.handleTimeout(TimeoutDeferredResultProcessingInterceptor.java:42)
at org.springframework.web.context.request.async.DeferredResultInterceptorChain.triggerAfterTimeout(DeferredResultInterceptorChain.java:75)
at org.springframework.web.context.request.async.WebAsyncManager$5.run(WebAsyncManager.java:392)
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.onTimeout(StandardServletAsyncWebRequest.java:143)
at org.apache.catalina.core.AsyncListenerWrapper.fireOnTimeout(AsyncListenerWrapper.java:44)
at org.apache.catalina.core.AsyncContextImpl.timeout(AsyncContextImpl.java:131)
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:157)
私は、ソフトウェアの次のバージョンを使用しています:
- 春ブーツ - > 1.5.4.RELEASE
- Tomcatの(スタンドアロンバイナリとしてインストール) - >はApache-Tomcatの-8.5.37
- モンゴDBバージョン:v3.4.10
- MongoDBのドライバ - 非同期:3.4.2
できるだけ早く私は、Tomcatサービスを再起動すると、すべてが正常に動作して開始します。
ヘルプには、何がこの問題の根本原因である可能性があります。
PS:私は使用していますDeferredResult
非同期のREST APIを作成するとCompletableFuture。
私も使って試してみましたがspring.mvc.async.request-timeout
、アプリケーションで構成されたとasynTimeout
Tomcatの中で。しかし、まだ同じエラーを取得。
これは、春はあなたの要求と投げタイムアウトしていることをおそらく明らかだAsyncRequestTimeoutException
あなたのクライアントに503背を返し、。
今の質問は、なぜこれが起こっているのか?2つの可能性があります。
これらは、正当なタイムアウトです。あなたが唯一の例外が表示されることを述べたときに、サーバーの負荷が増加。だから、おそらくあなたのサーバーは、ちょうどその負荷を処理することはできませんし、その性能は、いくつかの要求は春の時間の前にそれらを完了できない点まで劣化しています。
タイムアウトは、最終的には倍の春までそれを要求オープンを残して、原因プログラミングエラーに非同期の要求に対する応答を送信するために失敗し、サーバーによって引き起こされます。お使いのサーバがうまく例外を処理しない場合、この現象が発生するのは簡単です。お使いのサーバが同期している場合には未処理の例外は、クライアントへの応答の背中を送信するサーバフレームワークにまで反映されますので、それは例外処理と少しずさんなことしても大丈夫です。しかし、あなたには、いくつかの非同期コードで例外を処理するために失敗した場合、その例外が(おそらくいくつかのスレッドプールの管理コードで)他のどこかで捕捉され、そのコードは、演算の結果を待っている非同期要求があることを知るための方法はありませんそれが例外をスローしました。
それはあなたのアプリケーションについて詳しく知らなくても起こっかもしれないかを把握するのは難しいです。しかし、あなたが調査することができ、いくつかのものがあります。
まず、資源の枯渇を探してみてください。
- ガベージコレクタは、すべての時間を実行していますか?
- すべてのCPUが100%で釘付けにしていますか?
- OSは重くスワップされていますか?
- データベースサーバが別のマシン上にある場合は、資源枯渇の兆しを見せているマシンがありますか?
- どのように多くの接続がデータベースに開いていますか?接続プールがあれば、それは大変疲れていますか?
- どのように多くのスレッドを実行していますか?スレッドプールは、サーバーにある場合、それらは大変疲れていますか?
その限界で何かのは、おそらくそれは時間のうちに、あなたの要求を引き起こしているボトルネックになっている場合。
設定してみてくださいspring.mvc.async.request-timeout
に-1と何が起こるかをご覧ください。あなたは今だけゆっくりと、すべての要求に対する応答を取得するか、またはいくつかの要求が永久にハングアップするように見えるのですか?それは後者だ場合、それは強くあっ要求の失うトラックにそれを引き起こしているサーバーのバグだとレスポンスを送信するために失敗することを示唆しています。(設定がいる場合spring.mvc.async.request-timeout
は効果がないように見えます、そしてあなたが調査する必要がある次のことは、あなたが設定を設定するために使用しているメカニズムが実際に機能するかどうかです。)
私はこれらの場合に有用であることが分かってきたことを戦略が要求ごとに固有のIDを生成し、いくつかの文脈情報と一緒に、サーバーが非同期呼び出しを行うか、非同期呼び出しからの応答を受け取るいずれかのたびにIDを書き込むことで、各種の非同期ハンドラ内のチェックポイント。リクエストが行方不明に行く場合は、要求IDとどのサーバがその要求を最後にやっていたを把握するためにログ情報を使用することができます。
同様の戦略は、値は、要求が開始されたトラックとどのようなサーバーは、最後のその要求にやったことを対象としたマップに各要求のIDを保存することです。(この場合、サーバーは、各チェックポイントでこのマップを更新するのではなく、またはログへの書き込み、に加えている。)あなたは、要求IDを生成し、マップを維持するためのフィルタを設定することができます。あなたのフィルタが5xxの応答を送信するサーバーを見ている場合は、マップからその要求のための最後のアクションを記録することができます。
お役に立てれば!