web-dev-qa-db-ja.com

パフォーマンス-スプリングブート-サーバーの応答時間

スプリングブートアプリケーションで奇妙な動作があります。

  • フロントエンド/クライアント-angular 6
  • バックエンド-スプリングブート-スプリングMVC-組み込みTomcat-Linux

バックエンドを再起動した後、コントローラへの最初の呼び出しには約5秒かかります。次の同じリクエストには50msしかかかりません。これは90%のケースで再現可能であり、場合によっては最初の呼び出しでも高速です。

確かに、問題はクライアントではなくサーバーにあります。ブラウザで、TTFB時間(最初のバイトまでの時間)が5秒に増加しているのがわかります。次のリクエストに必要なのは、TTFBに10ミリ秒のみです。

サーバー上の監視ツール(アプリダイナミクス)を使用すると、このような遅いサーバーコールを収集でき、コールグラフで次のことがわかります。

org.Apache.catalina.webresources.JarWarResourceSet:getArchiveEntries:117

4916msが必要です。ここが私のボトルネックです。しかし、私はそれを修正する方法がわかりません。

私がすでに試したこと:

  • HikaricpからApache Tomcat jdbc接続プールに切り替えました
  • 2.0.0から2.0.5にアップグレードされたスプリングブーツ
  • Javaを1.8.0_181にアップグレードしました
  • プロパティspring.jpa.Tomcat.testOnBorrow = true
  • プロパティspring.jpa.Tomcat.validationQuery = select 1

サーバーの遅延に影響を与えないすべてのもの。

更新

Warファイルが複数回スキャンされるため、時間が失われます。

org.Apache.catalina.webresources.CachedResource.validateResourceは、warファイル(isPackedWarFile)およびこのチェックはfalseを返します。たとえwarファイルであっても。この誤動作のために、回避策があります。 Tomcat.resource.cache-ttを高い値に設定します。

しかし今org.Apache.catalina.webresources.Cache.getResourceにはnoCache 方法。このメソッドでは、classおよびjarファイルはキャッシュから除外されます。そして、これがwarファイルが再びスキャンされる理由です。

戦争ファイル全体のスキャンには約5秒かかります。そして、この休憩は世界の休憩の停止です。そして、このスキャンは、warファイルが展開されず、その内容を変更できないため、絶対に不要です。

更新

WarファイルをTomcatインストールに配置すると、すべてが高速になります。組み込みTomcatが問題です。

13
tomas

すでに行っていると思いますが、まだ行っていない場合は、 https://wiki.Apache.org/Tomcat/HowTo/FasterStartUp をご覧になり、そこで提案されている修正を実装してください。

埋め込みTomcatを使用したスキャンを無効にするには、ここのコメントに提案があります https://github.com/spring-projects/spring-boot/issues/161

上記の提案のどれもが遅延の修正に役立たない場合、考えられる回避策は、サーバーの起動時にその最初の要求を行うことです(そしてそこから遅延をトリガーします)。

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private RestTemplate template;

    public static void main (String args[]){
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        // do an initial request from here to trigger scanning the war
        template.exchange(...);
    }

}

これにより、クライアントは5秒の遅延を経験しなくなります。私はこれがハックであることを知っていますので、よりクリーンな方法を見つけた場合は代わりにそれを使用してください。

3
user10367961

CPU使用率が高く、応答が遅れるという同様の問題に直面していました。 org.Apache.catalina.webresources.JarWarResourceSet:getArchiveEntriesはwarファイルのスキャン中に約5秒かかっていました。スキャン中、リクエストは処理されませんでした。

この問題を解決したSpring boot version1.4.2.RELEASEから1.5.12.RELEASEに更新しました。実際、問題は埋め込みTomcatにあり、それは後のバージョンで修正されたようです。

1
Naveen Katiyar

実行可能[〜#〜] jar [〜#〜]ファイル(WARの代わりに)を使用して組み込みTomcatで実行すると、問題が解決しました。これは、実行可能なアーカイブからのリソースの読み込みを高速化するための 推奨方法 です。

  1. 1つのSpring Bootプロジェクトを作成し、JARまたはWARの両方にデプロイする
  2. パフォーマンスを向上させるためにWARからJARに切り替える必要があり、freemarkerでJSP taglibを使用するときに問題が発生しました。これは JSP taglibsを使用するときにその問題を解決する方法 です。
0
rochb

あなたが説明しているのは、重いDB接続プーリングを使用するインフラストラクチャの再起動の典型的な効果です。

  • 最初の要求:物理接続を開き(100ミリ秒から2〜3秒)、初期化を行い(DBに依存)、SQLを実行し(クエリごとに変化)、プールに戻ります(<1ミリ秒)
  • 2番目のリクエスト:プールからの抽出(<1ms)、SQLの実行(クエリごとに変化)、プールへの戻り(<1ms)

データに基づくと、最初の2つのステップは遅く、DBプールがウォームアップされるまで、非常に遅いクエリが発生するでしょう。潜在的な改善は次のとおりです。

  • tomcatがまだ応答していない間にプールが自己初期化を実行するウォームアップ期間を構成する
  • dB側で接続の作成時に行われていることを確認し、アプリ側でif /どの設定を設定する必要があるかを確認します
0
Simone Avogadro