Javaアプリケーションのパフォーマンスのボトルネックポイントが非常に大きく、例えば、ディスク、メモリ、ネットワークI / Oなど、Javaアプリケーションコード、JVM GC、データベース、キャッシュなどの全身因子。私が個人的な経験に基づいて、 アプリケーション層、データベース層、フレーム層、JVM層:Javaのパフォーマンスの最適化は、4つのレベルに分割され、図に示すように、。
図階層モデルのパフォーマンスの最適化1.Java
ますますハード各層の最適化、および問題関与を解決するための知識は異なります。例えば、アプリケーションロジック層は、コードを理解するJavaスレッドスタックによって、問題のコードの行を見つけ、そしてようにする必要があり、SQLを分析するデータベースレベルの必要性、デッドロックを配置するステップと、ソース・コード・フレームワークを理解する層の必要性、メカニズムを理解するための枠組み; GCに必要な作業のJVMレベルおよび種類メカニズムは、様々なパラメータJVMの向上の役割をよく理解しています。
オンサイト分析とポスト分析:Javaのパフォーマンス・チューニングの周りに、分析の2つの基本的な方法があります。
サイトの予約サイトによって分析して、診断ツールを使用して分析を探します。ライン上のサイトの分析大きなインパクト、シーンの一部は(特にそれがオンライン・ユーザークリティカルなビジネスに来るとき)は適していません。
その後の分析では、すぐにサービスを回復、マルチサイトデータとして収集する必要があるが、分析後、フィールドデータ収集のために再現しました。診断ツールのパフォーマンスからスタートしましょう、例と練習の数を共有しています。
まず、パフォーマンス診断ツール
一つは、同定されているパフォーマンスの問題とコードシステムの診断のためのパフォーマンス診断され、オンライン性能要求かどうかを判断する前、予めシステムパフォーマンステストの行のペアがあります。
前者について試験し、この論文では、後者は、様々なパフォーマンス測定ツール(例えばJMeterの)で押圧することができ、範囲は、本明細書で説明されていません。
:Javaアプリケーションのために、性能診断ツールは、主に二層に分割されるOSレベルとアプリケーションレベル(アプリケーション・コードの診断および診断GCを含む)は、Java。
OS診断
主要な関心事のOS診断は、三つの側面ではCPU、メモリ、I / Oです。
二、CPU診断
CPU平均負荷(平均負荷)、CPU使用率、コンテキスト切り替え(コンテキスト・スイッチ)のための主要な関心事。
トップコマンドによるシステムの負荷と平均CPU使用率を、見ることができる図2は、コマンドステータスを介してシステムの上面図です。
図の2.topコマンドの例。
63.66,58.39,57.18、それぞれ、上1分、5分、機械負荷の15分:3つの数の平均負荷。値はCPUの0.7未満*数である場合の経験によると、システムが正常に動作している。よりも、最大CPUコアの四、五倍の数に、この値は、より、システムの負荷が大幅に高くなっている場合。
図2において、負荷は、システムのロードの問題が生じる説明、57.18,1負荷は(16コアシステムの場合)63.66分で15分に達し、本傾向はさらに、具体的な理由を検索する必要性が高まっています。
図3に示したコマンド・コンテキスト・スイッチ、vmstatのCPUによって観察することができます。
図3.vmstatコマンドの例
コンテキストスイッチの発生のシーン数は、次の主要なカテゴリがあります。
-
1)タイムスライスは、CPU、通常のタスクのスケジューリングを満了します。
-
2)他のより高い優先度のタスクプリエンプションあります。
-
3)次に現在のタスク、タスクスイッチを一時停止し、タスクはI / O障害が発生した実行。
-
4)ユーザコードイニシアチブは、CPUを放棄する現在のタスクを一時停止します。
-
あるので、5)プリエンプティブマルチタスキング・リソース、何グラブが中断されていません。
-
6)ハードウェア割り込み。
共有リソースの競合から主に切り替えるJavaスレッドコンテキスト。ロックの粒度が大きすぎない限り、一般的に、単一のオブジェクトのロックシステムはほとんど、ボトルネックとなっていません。しかし、アクセス頻度が高い場合、コードのロックされたブロック内の連続する複数のオブジェクトは、コンテキストスイッチの多数現れるシステムのボトルネックになることができます。
三、メモリ
オペレーティングシステムの観点から、メモリ、アプリケーションプロセスの妥当性への配慮、ビューのメモリ使用量に無料-mコマンドを使用することができます。
あなたは、式VIRTによれば、トップコマンド仮想メモリVIRTと物理メモリRESによって使用されるプロセスを見ることができる= SWAP + RESを使用スワップパーティションの特定のアプリケーション(SWAP)、swappinessをできるJavaアプリケーションのパフォーマンスにスワップあまり効果の使用を算出することができます。できるだけ小さい値に移しました。
そのためJavaアプリケーションのために、メモリよりもはるかに遅く、すべての後に、パフォーマンス、ディスクパフォーマンスに影響を与えることができますあまりにも多くのスワップを取ります。
四、 I/O
I / Oは、ディスクI / O、ネットワークI / O、一般的にはI / Oのボトルネックになりやすいディスクを含んでいます。ディスクは、iostatので読み取るか、CPU I O待ちを通して見ることができる/ディスクI / Oが正常で見ることができます。
ディスクI / Oが遅い、またはディスクの障害を示す、高い状態にあった場合、それがパフォーマンスのボトルネック、アプリケーションの最適化やディスク交換の必要性となっています。
通常のトップは、ps、vmstatの、iostatのコマンドに加え、こうしたSolarisでmpstat、tcpdumpを、netstatコマンド、pidstat、SARなどなどのシステムの問題を診断するために、他のLinuxツールがあります。参考のため、図4に示すように、Linuxのブレンダン要約は、デバイス性能診断ツールの種類を示しています。
図パフォーマンス観察ツール4.Linux
五、Javaアプリケーションおよび診断ツール
アプリケーションコードは、パフォーマンス上の問題のクラスのパフォーマンスの問題を解決することは比較的容易です。いくつかのアプリケーションレベルの監視警報を通じ、そこに問題があると、コードはコードによって決定された場合は、直接配置することができ、またはトップ+のjstackを経由して、問題のスレッドスタックを識別し、問題に位置付けスレッドコードを、あなたは問題を見つけることができます。より複雑なため、論理以上のコードセグメント、ほとんどの場合、アプリケーション・コードは、パフォーマンスログを印刷してストップウォッチのパフォーマンスの問題を配置することができます。
診断スレッドスタック、GCおよび他の態様を含む一般的なJavaアプリケーションの診断。
jstack
トップコマンドを使用してjstackは、一般的に、トップ-H -p PID、再利用jstack -l pidの輸出スレッドスタックを介したJavaローカリゼーションプロセスとスレッドを使用しています。スレッドスタックは、このようにライン上で通常、3回のダンプ、通常はすべてのすべての5Sを複数のダンプを必要とする、一過性です。トップJavaスレッドの位置決めは、進に変わるのJavaスレッドのスタックNIDを取得し、PID、問題は、対応するスレッド・スタックで見つけることができます。
図5は、上部から長い時間Javaスレッドのためにどのように機能するかを見る-p -H
図5に示すように、ここで、24985を実行して、より長いスレッドは、問題を見つけるために0x6199のように対応するスレッドのスタックを見つけるために、Javaスレッドスタックによって進データに変換問題であってもよいです。
図6.jstack閲覧スレッドスタック
JProfilerを
図に示すようにJProfilerをは、CPU、ヒープ、メモリ分析、強力に実行することができます。圧力測定ツールと組み合わせることで、コードは、時間のかかるサンプリング統計することができます。
JProfilerをすることにより図7のメモリ分析
六、GC診断
JavaのGCは、プログラマのリスクがメモリを管理するアドレスが、GCの一時停止の適用はなっ解決すべき別の問題を引き起こしました。JDKはGCの問題、より一般的に使用されるJSTAT、jmapは、ならびにMATなどのサードパーティ製のツールを見つけるためのツールの範囲を提供します。
JSTAT
GC JSTATコマンドは、印刷可能な、若者のフルGCおよびGC周波数情報スタックを詳しく説明しています。コマンドのフォーマットは
JSTAT -gcxxx -t pidの<間隔> <数>、図に示すように。
図8.jstatコマンドの例
jmapの
jmapのjmapの-heap pidのプロセスのJavaヒープ情報を印刷します。jmapの-dumpによって:= XXX PIDスタックダンプファイルへのファイルは、さらに他のツールスタックを用いて解析することができます
マット
MATは、Javaヒープ解析ツールで直感的な診断レポートを提供し、内蔵OQLヒープクラスSQLクエリ、強力な、発信参照着信参照がオブジェクト参照を追跡することができる可能にします。
図の例9.MAT
図9は、MATを用いた例であり、MATは、2つの列は、オブジェクト、それぞれ浅いサイズ及び保持サイズの大きさを示し有し、前者は、メモリのサイズは、直接的または間接的に参照されるオブジェクト自体によって参照されるオブジェクトが含まれていないオブジェクト自体によって占有表します浅いオブジェクトのサイズとビーイングは、GCのメモリサイズを回復した後、オブジェクトが解放され、一般的な懸念で缶の大きさ。
オープンMATに大きなメモリを必要とするJavaアプリケーションのいくつかの杭(数十G)のために。
通常、ローカルの開発マシンのメモリが小さすぎると、それはビューのリモートオープン、サーバー側のインストールグラフィカル環境とMATオンラインで推奨され、開くことができません。マット杭またはコマンドを実行生の指標、ローカルコピーへのインデックスが、この方法に限定されているが、スタック情報を参照してください。
+ PrintGCDateStamps:問題のGCを診断するためには、JVM引数-XXを追加することを提案しました。図に示すようにGCパラメータが一般的に使用されます。
図10.一般的なGCパラメータ
トップで+ jstack + jmapの+ MATは、ほとんどのアプリケーションとメモリの問題を見つけることができますJavaアプリケーションの場合、それは不可欠なツールとして記述することができます。時には、Javaアプリケーションを使用すると、Zabbixの(OSおよび監視JVMを統合)などのより包括的な診断ツールのいくつかを使用し、その上ですることができ、OSの情報を診断する参照する必要があります。分散環境では、追跡システムを配布し、他のインフラストラクチャは、アプリケーションのパフォーマンス診断に強力なサポートを提供しています。
七、パフォーマンスの最適化の実践
パフォーマンスの後、いくつかの一般的に使用される診断ツールを導入した後、次のようにJVM層、アプリケーション層とコードのデータベース層からのケースの共有、中のJavaアプリケーションのチューニングで私たちの実践の一部を結合します。
JVMのチューニング:GC痛み
RMIリモーティングプロトコルの内部再建などのビジネスプラットフォームシステムを選択XX、サービスが応答ライン、数秒から数十秒までの休止時間を停止した後、システム上で定期的に表示されるようになりました。GCログを観察することによって打ち上げ以来、サービス後のその時間を見つけ全GCがあるでしょう。システムヒープが大きく設定されているので、完全なGCの停止時間が長い印加時間となり、オンラインリアルタイムサービス上のこの大きなインパクト。
分析の後、定期的に状況は完全なGCは、復興の前にシステムにしたがって、疑いのRMIフレームワークの寸法を表示されません。公開情報を通って、RMIのGDC(分散ガベージコレクション、分散ガベージコレクション)が2つのショーそのデーモンスレッドのコードをリスト、リモートオブジェクトを再利用するためのフルGCを実行し、定期的にデーモンスレッドを開始することを発見しました。
リスト2.DGCデーモンスレッドのソースコード
プライベート 静的の クラスデーモンは、拡張スレッド{ 公共 のボイドの実行を(){ のために(;;){ // ... 長い D = maxObjectInspectionAge(); もし(D> = L){ System.gc(); D = 0 ; } // ... } } }
比較的容易に解決するために問題を見つけた後。一つは、-XXを追加することです:+ DisableExplicitGCパラメータ、無効ショーは、直接GCシステムを呼び出しますが、NIOを使用したシステムは、外部メモリのヒープオーバーフローの危険性があるでしょう。
完全Stop-に、+ ExplicitGCInvokesConcurrent:パラメータ-XXを増加させながら別の方法は、大-Dsun.rmi.dgc.server.gcIntervalと-Dsun.rmi.dgc.client.gcInterval、フルGC間隔増大のパラメータを調整することによってですNIOアプリケーションが影響を受けることはありませんしながら、全GCの世界では、アプリケーションの休止時間を短縮、同時GCサイクルタイムに調整します。
有意三ヶ月後に減少の数を調整した後、図11、フルGCから分かります。
図11.Full GCの監視統計
大量のデータとの相互作用の高い同時実行アプリケーションのためのGCのチューニングは、特にJVMパラメータは、通常のビジネスニーズ、専門的なチューニングの必要性に満足していないデフォルトでは、まだ非常に必要です。GCログの解釈は、公開情報をたくさん持っている、これは行くことはありません。
GCチューニング対象の基本的な3つのアイデア:GCの頻度を減らすためには、不要なオブジェクトを減らすために、ヒープを増やすことによって生成することができ、GCの一時停止時間が減少し、CMS GCアルゴリズムを使用して、ヒープ領域を削減することによって、フルGC、調整トリガーCMSを回避します割合は、避け推進の障害と並行モード故障(歳が回収率をスピードアップするためにGCスレッドの数を増やし、より多くのスペースを割り当てる)、世代や他の大きなオブジェクトを低減します。
チューニングアプリケーション層:香り悪趣味コード
コードのチューニング開始のアプリケーション層からは、ルートは、コード効率、Javaアプリケーションのパフォーマンスを改善するための良い手段の間違いなく1の減少を引き起こします。
いくつかのマシンの負荷が急激に増加、すばやく演奏CPU使用率など、一定時間後(nginxの負荷分散を使用して)商用システムライン上の毎日、。私たちは、jmapのとjstackによって保存されているサーバーにオンラインおよびオンサイトの緊急ロールバックを持っていました。
スタックフィールドMATによる図12の分析
フィールドスタック12は、ダンプマットデータの分析によると、ほとんどの場合、メモリ・オブジェクトとバイト[]のjava.util.HashMap $エントリとして見出され、そして循環参照のjava.util.HashMap $ Entryオブジェクトがあります。予備は、ハッシュマップの処理PUTに無限ループの問題(図のjava.util.HashMap $エントリ0x2add6d992cb8サイクルフォーム0x2add6d992ce8次参照)が存在してもよい見つけます。
エラーにの同時使用の典型的な場面を位置付けるに属している関連文書へのアクセス(http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6423457)、簡単にプット、マルチスレッド機能を持っていないのHashMap自体があり、プット動作の複数のスレッドの場合には、アレイの形成された環状構造リストHashMapの内部拡張の内部につながるので、エンドレスループがあります。
・オンラインでは、最大の変化は、リスト3に示すように、両方の遅延ロード・メカニズムを使用して、メモリキャッシュのサイトデータを介してシステムのパフォーマンスを向上させることです。
3.ウェブサイトデータ遅延ロードのコードリスト
プライベート 静的な地図<ロング、UnionDomain> domainMap = 新しい新しいのHashMap <ロング、UnionDomain> (); プライベート ブールisResetDomains(){ IF (CollectionUtils.isEmpty(domainMap)){ // リモートサイトのhttpから詳細を取得するインタフェース 一覧<UnionDomain> = newDomains unionDomainHttpClient .queryAllUnionDomain()。 もし(CollectionUtils.isEmpty(domainMap)){ domainMap = 新しい HashMapの<ロング、UnionDomain> (); 用(UnionDomainドメイン:newDomains){ 場合(!ドメイン= ヌル){ domainMap.put(domain.getSubdomainId()、ドメイン); } } } 返す 真; } リターン はfalse ; }
DomainMapはここを参照してください静的な共有リソースであることができ、環構造、無限ループを形成し、その内部リストにつながるマルチスレッド状況で型のHashMapです。
複数のユーザーが同時にデータと初期化サイトを要求し、システムはnginxのは、樹脂容器を開始するためのユーザの要求を蓄積し再起動されているので、多くのユーザーがアプリケーションの流入を必要とし、フロントエンド接続とnginxのアクセスログを見ることができます並行性の問題が発生するのHashMapにつながる仕事、。解決策は比較的単純で故障箇所の後、主な解決策は以下のとおりです。
-
(1)ブロックの同期を使用するか、ConcurrentHashMapの同時の問題を解決します。
-
(2)完全なウェブサイトのキャッシュはシステムが起動する前にロードされ、遅延ロードなどでの除去。
-
分散キャッシュのようなローカル・キャッシュを交換する(3)。
不正なコードの位置決めのために、従来の意味でコードレビューに加えて、そのようなMATなどのツールを用いて迅速にある程度システムポイントのパフォーマンスのボトルネックを見つけることができます。しかし、最終的にするために、特定のシーンまたは結合業務データが、補助コードレビュー、パフォーマンステストツール、データラインと偶数シミュレート排水などの必要性に縛らいくつかのケースでは、パフォーマンス上の問題の原因を確認してください。以下は、私たちの不正なコードの一部をまとめたものであるかもしれないいくつかの機能、あなたの参考のために:
-
基本的なプログラミング仕様なしにコード(1)貧しい可読性、。
-
(2)オブジェクトの生成または生成大きすぎるオブジェクト、メモリリークなど。
-
(3)IO過大フロー操作、またはオフにすることを忘れ。
-
過剰(4)データベース操作、トランザクションが長すぎます。
-
(5)同期エラーのシナリオを使用して、
-
操作を消費する(6)ループ反復時間。
データベース層のチューニング:デッドロック悪夢
シーンデータベースと対話することは、特にOLTPのため、要求の厳しいアプリケーション、このデータの一貫性は非常に一般的ですほとんどのJavaアプリケーションでは、データベースのパフォーマンスは、直接アプリケーション全体のパフォーマンスに影響します。広告主および広告配信プラットフォーム、その適時性材料の一貫としてSogouのビジネスプラットフォームシステムは、高い要求を持って、我々はまた、いくつかの経験を蓄積してきたリレーショナルデータベースの最適化です。
材料ライブラリを宣伝するため、(特にバルク材料工具操作により)操作のより高い周波数が非常に簡単に、より一般的なシナリオの一つは、材料価格調整をアドバタイズされた、データベースのデッドロック状況が発生もたらします。お客様が入札物質の頻繁に調整する傾向があり、ひいては間接的にも、デッドロックの可能性に貢献したデータベース・システムをロードするために大きな圧力を引き起こします。下には広告システムの場合Sogouのビジネスプラットフォーム広告素材の価格調整について説明します。
日訪問商用システムの急激な増加は、増加したシステム負荷とデータベース頻繁にデッドロックが生じる、デッドロックステートメントは、図13に示されています。
図13.デッドロック声明
前記は、MySQL InnoDBエンジンを使用して、インデックステーブルidx_groupdomain_accountid(accountIdを)一次、idx_groupdomain_groupid(グループID)、3つの単一のインデックス構造(groupdomainid)をgroupdomain。
グループ入札を更新し、シーングループ、業界団体(groupindusテーブル)とグループのウェブサイト(groupdomainテーブル)がある場合、このシナリオが発生します。
業界団体の入札は、グループ入札(それが利用グループの入札であれば、isusegrouppriceでマーク)を使用している場合、グループの入札を更新するとき。(それは業界団体の入札を使用する場合、isuseinduspriceでマーク)入札チームWebサイトは、業界団体の入札を使用している場合、同時に、グループはまた、同社のWebサイトの入札を更新する必要があります。3000サイト以下の各グループの最大の可能なので、その関連レコードになります長いグループの入札を更新するときは、ロックされました。
デッドロックの問題は、トランザクション1、上から見ることができ、トランザクション2は、単一のインデックスをidx_groupdomain_accountid選択されます。MySQLのInnoDBエンジンロックによると、単一のトランザクションでの特徴は、インデックスを使用することを選択しますが、セカンダリインデックスの使用がロックされたら場合、主キーのインデックスをロックしようとします。2トランザクション要求保持(「空間ID 5726ページなし8658 Nビット824指数 『のロックされた範囲)idx_groupdomain_accountid`セカンダリインデックス 'が、トランザクションにおけるロックトランザクションが二次インデックス2(』空間となっていることをさらに分析ショーID 5726ページには8658のnビット824インデックス」)を添加ロック、主キーインデックスプライマリインデックスのロックを待っているロック要求。待機中のトランザクションの実行時間が長すぎるか、2長い時間、最終的な1を発生し、ロールバックトランザクションで、その結果、ロックを解除しません。
日間の訪問履歴の追跡が見ることができることで、ロックを解除する前のトランザクションのキーPRIMARYインデックスを待って次ループにおける多数のトランザクションで、その結果、その日のスクリプト道を経由して、グループの事業を促進するため、顧客の入札によって開始の修正が多数あります。この問題は顕著ではないOracleデータベースの限られた用途のために、問題の原因インデックスMySQLのInnoDBエンジンで実際に嘘。
自然な方法は、単一のトランザクションロックできるだけレコード数を解決することであり、このデッドロックの確率が大幅に削減されます。最終用途(accountIdを、グループID)複合インデックス、単一のトランザクションロック内のレコードの数を減らすだけでなく、それによって、そのようなデッドロックの発生確率を低下させる、異なるプログラム中のデータ・レコードの分離の実現を促進します。
一般的に、我々は基本的に次の側面からスタートするデータベース層を調整するために、話します:
(1)SQL文のレベルを最適化するには:スローSQL分析、インデックス分析とチューニング、スプリットおよびその他の事項を。
(2)データベースの構成レベルを最適化する。そのようなフィールドは、バッファサイズ、ディスクI / O、データベース・パラメータの最適化、データの最適化を調節するように設計されています。
構造レベル最適化するデータベースから(3):分割垂直および水平分割データベースを考慮し、等。
(4)適切なデータベースエンジンを選択する等の導入を検討し、このようなNoSQLのようなシーンの異なるタイプに適応。
八、要約と提言
2-8チューニングは同じ原理に従う、パフォーマンスの問題は、このようにキーコード乗算器を最適化する、生成されたコードの20%から80%です。同時に、過剰最適化がより多くの問題を引き起こすことがあり、やってオンデマンド最適化のパフォーマンスを最適化します。Javaのパフォーマンス・チューニングのために、システムアーキテクチャ、アプリケーションのコードを理解するだけでなく、同じ注意JVMレベル、さらには基礎となるオペレーティング・システムが必要です。メインを要約すると、以下の点から考えることができます。
1)チューニングと性能
塩基特性は、本明細書中にハードウェア・レベルを指し、またはシステム・バージョン・アップグレード、ハードウェアの最適化を操作する、そのようなネットワークのチューニングとして、オペレーティングシステムレベルの最適化をアップグレードします。F5のハードドライブとSDDは、Linuxの新しいバージョンを含む、導入された使用は、性能のNIOの側面をアップグレードするなど、大幅にアプリケーションを促進することができます。
2)データベースのパフォーマンスの最適化
共通業務の分割、インデックスのチューニング、SQLの最適化、および含めNoSQLのは、このようなトランザクションが分割され、非同期処理の導入として、導入、そして最終的に特定のシーンのためのNoSQLデータベースの様々なタイプの導入など実践の一貫性の導入を、達成他、大幅に高い同時実行の下で従来のデータベースの不足を緩和することができます。
3)アプリケーションフレームワークは、最適化
計算元のクラスタのパフォーマンスのボトルネックを解決するために、新しい機能と、いくつかの新しいコンピューティングやストレージフレームワークを導入する等、又は分散戦略の導入を含む、コンピューティングおよびストレージのレベル時間のための典型的な練習空間を使用して、事前に事前に計算等等、システムの負荷をある程度低減することができます。
最適化の4)動作レベル
テクノロジーは、実際には、あなたが最も頻繁に、実際には、可能ならば、ビジネスにおけるEVADEや調整に、ために生じる特殊なビジネスシナリオの大部分を見ることができ、パフォーマンスの問題の多くのシーンでは、システムの性能を向上させる唯一の手段ではありません効果的。