web-dev-qa-db-ja.com

グローバルなTomcat / JVMのスローダウンの原因は何ですか?

Tomcat 7でJava EE-ish Webアプリケーション(Hibernate 4 + Spring + Quartz + JSF + Facelets + Richfaces))のいくつか(約15)のインスタンスを実行する奇妙で深刻な問題が発生しています/ Java 7。

システムは正常に動作しますが、非常にさまざまな時間が経過した後、アプリケーションのすべてのインスタンスが同時に応答時間の増加に突然悩まされます。基本的にはアプリケーションは動作しますが、応答時間は約3倍長くなります。

これは、2つのサンプルインスタンスの2つの特定の短いワークフロー/アクション(ログイン、セミナーのアクセスリスト、このリストのajax更新、ログアウト。下の行はajax更新のリクエスト時間)の応答時間を表示する2つの図です。アプリケーションの:

Response times of context 1Resoinse times of context 2

ご覧のとおり、アプリケーションの両方のインスタンスがまったく同時に「爆発」し、遅くなります。サーバーを再起動すると、すべてが正常に戻ります。アプリケーションのすべてのインスタンスが同時に「爆発」します。

セッションデータをデータベースに保存し、これをクラスタリングに使用しています。セッションのサイズと数を確認しましたが、どちらもかなり低いです(つまり、他のアプリケーションを使用する他のサーバーでは、より多くのセッションが存在することがあります)。クラスター内の他のTomcatは、通常、さらに数時間高速にとどまり、このランダムな時間の後、「死ぬ」こともあります。 jconsoleでヒープサイズをチェックし、メインヒープは2.5〜1 GBのサイズのままです。db接続プールは基本的に空き接続とスレッドプールでいっぱいです。最大ヒープサイズは5 GBで、perm genスペースも十分にあります。負荷は特に高くありません。メインCPUの負荷は約5%です。サーバーはスワップしません。また、アプリケーションをVMに追加してデプロイしたため、問題は同じままであるため、ハードウェアの問題もありません。

どこを見ればいいのかわからない、アイデアが出ていない。誰かがどこを見るべきか考えていますか?

2013-02-21更新:新しいデータ!

さらに2つのタイミングトレースをアプリケーションに追加しました。測定に関しては、監視システムは2つのタスクを実行するサーブレットを呼び出し、サーバー上のそれぞれの実行時間を測定し、応答としてかかった時間を書き込みます。これらの値は、監視システムによって記録されます。

いくつかの興味深い新しい事実があります。アプリケーションのホットな再デプロイメントにより、現在のTomcat上のこの単一のインスタンスが異常になります。これは、生のCPU計算パフォーマンスにも影響を与えるようです(以下を参照)。この個別のコンテキストの爆発は、ランダムに発生する全体のコンテキストの爆発とは異なります。

いくつかのデータについて:

Diagram 3Diagram 4

最初に個々の行:

  1. 水色は、クライアントで測定された小さなワークフロー(詳細は上記を参照)の合計実行時間です。
  2. 赤は水色の「一部」であり、クライアントで測定されたそのワークフローの特別なステップを実行するのにかかった時間です
  3. ダークブルーはアプリケーションで測定され、Hibernateを介してDBからエンティティのリストを読み取り、そのリストを反復処理し、遅延コレクションと遅延エンティティを取得します。
  4. 緑は、浮動小数点演算と整数演算を使用した小さなCPUベンチマークです。オブジェクトの割り当てがない限り、ゴミはありません。

爆発の個々の段階について:各画像に3つの黒い点をマークしました。 1つ目は、1つだけのアプリケーションインスタンスでの「小さな」爆発です。Inst1ではジャンプし(特に赤い線で表示)、Inst2は多少落ち着きます。

この小さな爆発の後、「ビッグバン」が発生し、そのTomcat上のすべてのアプリケーションインスタンスが爆発します(2番目のドット)。この爆発は、すべての高レベルの操作(要求処理、DBアクセス)に影響しますが、not CPUベンチマークに影響することに注意してください。両方のシステムで低いままです。

その後、context.xmlファイルをタッチしてInst1をホット再デプロイしました。先ほど言ったように、このインスタンスは爆発から完全に破壊された状態になりました(水色の線はチャートから外れています-約18秒です)。 a)この再デプロイメントはInst2にまったく影響を与えないこと、およびb)Inst1のraw DBアクセスにも影響を与えないことに注意してください-しかし、CPUが突然遅くなったようです!。これはおかしい、と私は言います。

更新の更新 Tomcatのリーク防止リスナーは、アプリケーションがアンデプロイされたときに古いThreadLocalsまたはThreadsについて警告しません。明らかにクリーンアップの問題があるように思われます(これはBig Bangに直接関連していないと思われます)が、Tomcatにはヒントがありません。

2013-02-25更新:アプリケーション環境とクォーツスケジュール

アプリケーション環境はそれほど洗練されていません。ネットワークコンポーネントは別として(それらについては十分に知りません)、基本的に1つのアプリケーションサーバー(Linux)と2つのデータベースサーバー(MySQL 5およびMSSQL 2008)があります。主な負荷はMSSQLサーバーにあり、もう1つは単にセッションを保存する場所として機能します。

アプリケーションサーバーは、2つのTomcat間でロードバランサーとしてApacheを実行します。そのため、同じハードウェア上で2つのJVMを実行しています(2つのTomcatinstances)。この構成は、アプリケーションサーバーがアプリケーションを正常に実行できるため(実際には何年も前から)負荷を実際に分散するのではなく、ダウンタイムなしで小さなアプリケーションの更新を可能にするために使用します。問題のWebアプリケーションは、Tomcatごとに約15コンテキストの異なる顧客向けに、個別のcontextsとしてデプロイされます。 (私の投稿で「インスタンス」と「コンテキスト」を混同しているようです-ここではオフィスで同義語として使用されることが多く、通常は同僚が話していることを魔法のように知っています。

より良い表現で状況を明確にするため:私が投稿した図は、同じJVM上の同じアプリケーションの2つの異なるコンテキストの応答時間を示しています。 Big Bangは、1つのJVMのすべてのコンテキストに影響しますが、他のJVMでは発生しません(Tomcatが爆発する順序はランダムです)。ホット再デプロイ後、1つのTomcatインスタンスの1つのコンテキストが非常に複雑になります(そのコンテキストのCPUが一見低速に見えるなど、すべての面白い副作用があります)。

システムの全体的な負荷はかなり低いです。これは、約30人のアクティブユーザーが同時に存在する内部コアビジネス関連ソフトウェアです。現在、アプリケーション固有の要求(サーバータッチ)は1分あたり約130です。単一のリクエストの数は少ないですが、リクエスト自体はしばしばデータベースに対して数百の選択を必要とするため、かなり高価です。しかし、通常はすべてが完全に受け入れられます。また、アプリケーションは大きな無限キャッシュを作成しません。一部のルックアップデータはキャッシュされますが、それは短時間だけです。

上記で書いたように、サーバーは数年間アプリケーションを正常に実行できます。問題を見つける最良の方法は、最初に問題が発生した正確なタイミングを見つけて、この時間枠(アプリケーション自体、関連するライブラリまたはインフラストラクチャ)で何が変更されたかを確認することであることを知っていますが、問題は問題が最初にいつ発生したかはわかりません。準最適な(不在の意味で)アプリケーション監視を呼び出しましょう...:-/

私たちはいくつかの側面を除外しましたが、アプリケーションは先月中に数回更新されました。古いバージョンを単純に展開することはできません。機能の変更ではなかった最大の更新は、JSPからFaceletsへの切り替えでした。しかし、それでも、「何か」がすべての問題の原因であるに違いありませんが、たとえばFaceletsが純粋なDBクエリ時間に影響する理由はわかりません。

石英

Quartzのスケジュールについては、合計8つのジョブがあります。それらのほとんどは1日に1回だけ実行され、大容量データの同期に関係しています(「ビッグデータラージ」のように「ラージ」ではありません。これは、通常のユーザーが日常の作業で見る以上のものです)。ただし、これらのジョブはもちろん夜間に実行され、日中に問題が発生します。ここでは詳細なジョブリストを省略します(有益な場合は、もちろん詳細を提供できます)。ジョブのソースコードは、ここ数か月間変更されていません。爆発が仕事と一致するかどうかはすでに確認しましたが、結果はせいぜい決定的ではありません。私は実際にはそれらが整合していないと言いますが、毎分実行されるいくつかのジョブがあるので、私はまだそれを除外することはできません。私の意見では、毎分実行される実際のジョブは非常に軽量であり、通常、データが利用可能かどうか(異なるソース、DB、外部システム、電子メールアカウント)をチェックし、そうであればDBに書き込むか、別のシステムにプッシュします。

ただし、個々のジョブ実行の開始および終了タイムスタンプを正確に確認できるように、現在、個々のジョブ実行のログを有効にしています。おそらくこれはより多くの洞察を提供します。

2013-02-28更新:JSFのフェーズとタイミング

JSF phaeリスナーをアプリケーションに手動で追加しました。サンプル呼び出し(ajaxの更新)を実行しましたが、これは私が持っているものです(左:通常の実行中のTomcatインスタンス、右:Big Bang後のTomcatインスタンス-数は両方のTomcatからほぼ同時に取得され、ミリ秒単位です):

  1. RESTORE_VIEW:17対46
  2. APPLY_REQUEST_VALUES:170対486
  3. PROCESS_VALIDATIONS:78対321
  4. UPDATE_MODEL_VALUES:75対307
  5. RENDER_RESPONSE:1059対4162

Ajaxの更新自体は、検索フォームとその検索結果に属します。また、アプリケーションの最も外側のリクエストフィルターとWebフローが動作を開始する間に別の遅延があります。Webフローの特定のフェーズにかかる時間を測定するFlowExecutionListenerAdapterがあります。このリスナーは、未展開のTomcatでの完全なリクエストの合計1632ミリ秒のうち、「リクエストが送信された」(最初のWebフローイベントを知る限り)で1405ミリ秒と報告します。
ただし、Tomcatの展開では、合計要求時間7105ミリ秒のうち、送信された要求に対して5332ミリ秒(すべてのJSFフェーズが発生することを意味します)を報告します。 Webフローのリクエストの送信。
測定フィルターの下で、フィルターチェーンにorg.ajax4jsf.webapp.BaseFilterが含まれている場合、Springサーブレットが呼び出されます。

2013年6月5日更新:過去数週間で行われているすべてのこと

小規模でかなり遅れた更新...しばらくするとアプリケーションのパフォーマンスが低下し、動作が不安定になります。プロファイリングはまだ役に立たず、分析するのが難しい膨大な量のデータを生成しただけです。 (実稼働システムのパフォーマンスデータを調べたり、プロファイルを作成してみてください...ため息)いくつかのテスト(ソフトウェアの特定の部分の取り出し、他のアプリケーションのアンデプロイなど)を実施し、実際にはアプリケーション全体に影響するいくつかの改善がありました。 EntityManagerのデフォルトのフラッシュモードはAUTOで、ビューのレンダリング中に、フラッシュが必要かどうかのチェックを含め、常に多くのフェッチと選択が発行されます。
したがって、RENDER_RESPONSE中にフラッシュモードをCOMMITに設定するJSFフェーズリスナーを構築しました。これにより、全体的なパフォーマンスが改善され、多くのようになり、問題が多少緩和されたようです。

しかし、アプリケーションの監視により、Tomcatインスタンスの一部のコンテキストで完全に異常な結果とパフォーマンスが得られます。 1秒未満で終了する(実際に展開後に実行する)アクションのように、4秒以上かかるようになりました。 (これらの数値はブラウザの手動タイミングでサポートされているため、問題の原因は監視ではありません)。

たとえば、次の図を参照してください。
Diagram

この図は、同じコンテキスト(同じdb、同じ構成、同じjar)を実行している2つのTomcatインスタンスを示しています。再び青い線は、純粋なDB読み取り操作(エンティティのリストを取得し、それらを反復処理し、コレクションと関連データを遅延取得します)にかかった時間です。ターコイズのような線と赤い線は、それぞれいくつかのビューをレンダリングし、ajaxの更新を行うことで測定されます。ターコイズ色と赤の2つのリクエストによってレンダリングされたデータは、青い線で照会されたものとほとんど同じです。

インスタンス1(右)で約0700になりましたが、実際のレンダリング応答時間にも影響を与えると思われる純粋なDB時間の大幅な増加がありますが、Tomcat 1のみです。Tomcat0はこの影響をほとんど受けません。同じ物理ハードウェア上で両方のTomcatが実行されているサーバーまたはネットワーク。 Javaドメインのソフトウェアの問題である必要があります。

前回のテストで興味深いことがわかりました。すべての応答には「X-Powered-By:JSF/1.2、JSF/1.2」というヘッダーが含まれています。一部(WebFlowによって生成されたリダイレクト応答)には、「JSF/1.2」が3回も含まれています。
これらのヘッダーを設定するコード部分をトレースしましたが、このヘッダーが最初に設定されるのは、このスタックが原因です。

... at org.ajax4jsf.webapp.FilterServletResponseWrapper.addHeader(FilterServletResponseWrapper.Java:384)
at com.Sun.faces.context.ExternalContextImpl.<init>(ExternalContextImpl.Java:131)
at com.Sun.faces.context.FacesContextFactoryImpl.getFacesContext(FacesContextFactoryImpl.Java:108)
at org.springframework.faces.webflow.FlowFacesContext.newInstance(FlowFacesContext.Java:81)
at org.springframework.faces.webflow.FlowFacesContextLifecycleListener.requestSubmitted(FlowFacesContextLifecycleListener.Java:37)
at org.springframework.webflow.engine.impl.FlowExecutionListeners.fireRequestSubmitted(FlowExecutionListeners.Java:89)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.Java:255)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.Java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.Java:183)
at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.Java:174)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.Java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.Java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:641)
... several thousands ;) more

このヘッダーが2回目に設定される

at org.ajax4jsf.webapp.FilterServletResponseWrapper.addHeader(FilterServletResponseWrapper.Java:384)   
at com.Sun.faces.context.ExternalContextImpl.<init>(ExternalContextImpl.Java:131)   
at com.Sun.faces.context.FacesContextFactoryImpl.getFacesContext(FacesContextFactoryImpl.Java:108)   
at org.springframework.faces.webflow.FacesContextHelper.getFacesContext(FacesContextHelper.Java:46)   
at org.springframework.faces.richfaces.RichFacesAjaxHandler.isAjaxRequestInternal(RichFacesAjaxHandler.Java:55)   
at org.springframework.js.ajax.AbstractAjaxHandler.isAjaxRequest(AbstractAjaxHandler.Java:19)   
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.createServletExternalContext(FlowHandlerAdapter.Java:216)   
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.Java:182)   
at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.Java:174)   
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.Java:48)   
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:925)   
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:856)   
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:920)   
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.Java:827)   
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:641)

これが問題を示しているかどうかはわかりませんが、サーバーで実行されている他のアプリケーションではこれに気付かなかったので、ヒントが得られるかもしれません。私は本当にそのフレームワークのコードが何をしているのか全くわかりません(確かに私はまだそれに飛び込みませんでした)...おそらく誰かがアイデアを持っていますか?または、行き止まりに陥っていますか?

付録

私のCPUベンチマークコードは、Math.tanを計算し、その結果値を使用してサーブレットインスタンスの一部のフィールドを変更するループ(揮発性/同期なし)で構成され、次にいくつかの生の整数計算を実行します。これはそれほど洗練されたものではありませんが、よくわかります...チャートに何かを表示しているようですが、それが何を示しているのかわかりません。 HotSpotが貴重なコードをすべて最適化することを防ぐために、フィールドの更新を行います;)

    long time2 = System.nanoTime();
    for (int i = 0; i < 5000000; i++) {
        double tan = Math.tan(i);
        if (tan < 0) {
            this.l1++;
        } else {
            this.l2++;
        }
    }

    for (int i = 1; i < 7500; i++) {
        int n = i;
        while (n != 1) {
            this.steps++;
            if (n % 2 == 0) {
                n /= 2;
            } else {
                n = n * 3 + 1;
            }
        }
    }
    // This execution time is written to the client.
    time2 = System.nanoTime() - time2;
41
chammp

解決

コードキャッシュの最大サイズを増やします。

-XX:ReservedCodeCacheSize=256m

バックグラウンド

Tomcat 7およびJava 1.7.0_15で動作するColdFusion 10を使用しています。私たちの症状はあなたの症状と似ていました。サーバーの応答時間とCPU使用率は、明らかな理由はありませんが、CPUが遅くなったように見えましたが、ColdFusion(およびTomcat)を再起動するしかありませんでした。

初期分析

まず、メモリ使用量とガベージコレクターログを確認しました。問題を説明できるものは何もありませんでした。

次のステップは、1時間ごとにヒープダンプをスケジュールし、VisualVMを使用して定期的にサンプリングを実行することでした。目標は、スローダウンの前後にデータを取得して比較できるようにすることでした。私はそれを達成することができました。

際立っていたサンプリングには、coldfusion.runtime.ConcurrentReferenceHashMapのget()という関数が1つありました。減速前に比べて、減速後に多くの時間が費やされました。関数がどのように機能するかを理解するのに少し時間を費やし、ハッシュ関数に問題があり、いくつかの巨大なバケツが生じる可能性があるという理論を開発しました。ヒープダンプを使用すると、最大のバケットには6つの要素しか含まれていないことがわかり、その理論を破棄しました。

コードキャッシュ

「Java Performance:The Definitive Guide」を読んだとき、ようやく正しい軌道に乗った。 JITコンパイラに関する章があり、これまで聞いたことのないコードキャッシュについて説明しています。

無効なコンパイラ

実行されたコンパイル数(jstatで監視)とコードキャッシュのサイズ(VisualVMのメモリプールプラグインで監視)を監視すると、サイズが最大サイズ(この環境ではデフォルトで48 MB)まで増加することがわかりました- -デフォルトはJavaバージョンおよびJavaコンパイラ)によって異なります。コードキャッシュがいっぱいになると、JITコンパイラはオフになりました。コンパイラは無効になっています。」と表示されますが、そのメッセージは表示されませんでした。使用しているバージョンにそのメッセージがない可能性があります。実行されたコンパイルの数が停止したため、コンパイラがオフになったことがわかります増加しています。

最適化の継続

JITコンパイラーは、以前にコンパイルされた関数を非最適化できます。これにより、関数がインタープリターによって再度実行されるようになります(関数が改善されたコンパイルに置き換えられない限り)。最適化されていない関数をガベージコレクションして、コードキャッシュのスペースを解放できます。

何らかの理由で、それらを置き換えるためにコンパイルされたものが何もない場合でも、関数は最適化解除され続けました。より多くのメモリがコードキャッシュで使用可能になりますが、JITコンパイラは再起動されませんでした。

スローダウンが発生したときに-XX:+ PrintCompilationを有効にしたことはありませんでしたが、ConcurrentReferenceHashMap.get()、または依存する関数のいずれかがその時点で最適化解除されたことは間違いないでしょう。

結果

コードキャッシュの最大サイズを256 MBに増やしたため、速度の低下は見られず、一般的なパフォーマンスの向上も見られました。現在、コードキャッシュには110 MBがあります。

44
Jonas Meller

最初に、問題に関する詳細な事実を取得する素晴らしい仕事をしたと言いましょう。知っていることや推測していることを明確にする方法がとても気に入っています。本当に役立ちます。

EDIT 1コンテキストとインスタンスの更新後の大規模な編集

除外できます:

  • GC(CPUベンチマークサービススレッドに影響し、メインCPUを急上昇させる)
  • クォーツジョブ(TomcatまたはCPUベンチマークの両方に影響する)
  • データベース(両方のTomcatに影響します)
  • ネットワークパケットストームなど(両方のTomcatに影響します)

あなたが苦しんでいるのは、JVMのどこかでレイテンシーの増加であると信じています。遅延とは、スレッドがどこかからの応答を(同期的に)待機する場所です。これにより、サーブレットの応答時間が長くなりますが、CPUに負荷はかかりません。典型的なレイテンシは次の原因で発生します。

  • を含むネットワークコール
    • JDBC
    • EJBまたはRMI
    • JNDI
    • DNS
    • ファイル共有
  • ディスクの読み取りと書き込み
  • スレッド
    • キューからの読み取り(および書き込み)
    • synchronizedメソッドまたはブロック
    • futures
    • Thread.join()
    • Object.wait()
    • Thread.sleep()

問題がレイテンシーであることを確認する

市販のプロファイリングツールの使用をお勧めします。 [JProfiler]( http://www.ej-technologies.com/products/jprofiler/overview.html 、15日間の試用版が利用可能)が好きですが、 YourKit もStackOverflowコミュニティによって推奨されています。この議論では、JProfilerの用語を使用します。

正常に実行されている間にTomcatプロセスにアタッチし、通常の条件下でどのように見えるかを把握します。特に、高レベルのJDBC、JPA、JNDI、JMS、サーブレット、ソケット、およびファイルプローブを使用して、JDBC、JMSなどの操作にかかる時間を確認します( screencast 。次の製品のスクリーンショットでは、JPAプローブを使用してSQLのタイミングを確認できます。

JPA hotspots
(ソース: ej-technologies.com

ただし、プローブが問題を特定しなかった可能性があります。たとえば、スレッドの問題の可能性があります。アプリケーションの[スレッド]ビューに移動します。これにより、各スレッドの状態の実行中のグラフが表示され、Object.wait()でCPUで実行されているか、synchronizedブロックに入るのを待っているか、ネットワークI/O。どのスレッドが問題を示しているかがわかったら、CPUビューに移動し、スレッドを選択し、スレッド状態セレクターを使用して、すぐに高価なメソッドとその呼び出しスタックにドリルダウンします。 [スクリーンキャスト](( screencast )。アプリケーションコードにドリルアップできます。

これは、実行可能時間の呼び出しスタックです。

enter image description here

これは同じものですが、ネットワーク遅延を示しています。

enter image description here

whatがブロックしていることがわかったら、解決への道がより明確になることを願っています。

9
Andrew Alcock

G1ガベージコレクターで実行しているJava 1.7.0_u101(最新の公開JDK/JRE 7は1.7.0_u79であるため、Oracleのサポートされているバージョンの1つ)で実行)と同じ問題がありました。他のJava 7バージョンまたは他のGCで問題が発生するかどうかを伝えます。

私たちのプロセスは、Liferayポータルを実行するTomcatでした(Liferayの正確なバージョンはここでは重要ではないと思います)。

これは私たちが観察した動作です。5GBの-Xmxを使用すると、起動直後の初期コードキャッシュプールサイズは約40MBでした。しばらくすると、約30MBに低下しました(起動時に実行中のコードが大量に実行され、それらは二度と実行されないため、しばらくするとキャッシュから削除されることが予想されます)。 JITアクティビティがあることがわかったため、実際にJITがキャッシュを埋めました(後で説明するサイズと比較すると、ヒープサイズ全体に対するキャッシュサイズが小さいため、JITに厳しい要件が課されているようです。後者はかなり神経質にキャッシュを削除します)。しかし、しばらくすると、これ以上コンパイルが行われなくなり、JVMが非常に遅くなりました。時々Tomcatを強制終了して適切なパフォーマンスを取り戻す必要がありました。ポータルにコードを追加すると、問題はますます悪化しました(コードキャッシュがすぐに飽和するためだと思います)。

JDK 7 JVMには、JITを再起動しないバグがいくつかあるようです(このブログ投稿を参照してください: https://blogs.Oracle.com/poonam/entry/why_do_i_get_message )、 JDK 7でも、緊急フラッシュ後(ブログではJavaバグ8006952、8012547、8020151、および8029091)に言及しています)。

これが、緊急フラッシュが発生する可能性が低いレベルまでコードキャッシュを手動で増やすことで問題を「修正」する理由です(JDK 7の場合はそうだと思います)。

私たちのケースでは、コードキャッシュプールサイズを調整する代わりに、Java 8にアップグレードすることを選択しました。これにより、問題が修正されたようです。また、コードキャッシュはより大きい(起動サイズは約200MB、巡航サイズは約160MBになります。)予想通り、あるアイドル時間の後、キャッシュプールサイズが低下し、ユーザー(またはロボットなど)がサイトを閲覧すると再び立ち上がる、より多くのコードが実行されます。

上記のデータがお役に立てば幸いです。

言うのを忘れていました:この記事の説明、裏付けデータ、推論ロジック、結論が非常に役立つことがわかりました。本当にありがとう!

2
avarvit

JVM GC時間を確認しましたか?一部のGCアルゴリズムは、アプリケーションスレッドを「一時停止」し、応答時間を長くする場合があります。

jstat ユーティリティを使用して、ガベージコレクションの統計情報を監視できます。

jstat -gcutil <pid of Tomcat> 1000 100

上記のコマンドは、1秒ごとに100回GC統計情報を出力します。 FGC/YGCカラムを見てください。数値が増え続ける場合は、GCオプションに問題があります。

応答時間を低く保ちたい場合は、CMS GCに切り替えることができます。

-XX:+UseConcMarkSweepGC

他のGCオプションを確認できます here

1
ericson

アプリのパフォーマンスがしばらく低下した後はどうなりますか?もしそうなら、私は現時点で行われているアプリに関連していないアクティビティがあるかどうかを確認します。ウイルス対策スキャンやシステム/データベースのバックアップのようなもの。

そうでない場合は、プロファイラー(JProfiler、yourkitなど)で実行することをお勧めします。このツールを使用すると、非常に簡単にホットスポットを参照できます。

1
Doron Manor

誰かがどこを見るべきか考えていますか?

  1. Tomcat/JVMに問題がある可能性があります。一般的なデータベースのように共有リソースを起動してストレスをかけるバッチジョブはありますか?

  2. スレッドダンプを取得し、アプリケーションの応答時間が爆発したときにJavaプロセスが何をしているかを確認しますか?

  3. Linuxを使用している場合は、straceなどのツールを使用して、Javaプロセスが実行していることを確認してください。

1
Bimalesh Jha

時限プロセスを管理するQuartzを使用していますが、これは特定の時間に行われるようです。

Quartzのスケジュールを投稿し、それが一致するかどうかをお知らせください。そうであれば、リソースを消費するためにどの内部アプリケーションプロセスが開始されるかを判断できます。

または、アプリケーションコードの一部が最終的にアクティブ化され、メモリキャッシュにデータをロードすることを決定する可能性があります。 Hibernateを使用しています。データベースへの呼び出しを確認し、何かが一致するかどうかを確認します。

0
JoshDM