JVM 関連の例外は、最前線の開発者にとって常に頭痛の種でした。なぜなら、ビジネス コードの場合、JVM の動作は基本的にブラック ボックスだからです。例外が発生した場合、直感的に問題を確認して見つけることは困難です。だからこそ、その内部ロジックを研究する必要があるのです。 この記事では、最近のオンライン JVM メモリ リークの例を使用して分析します。 パート1 オンラインサーバーが警報を発令ある日、同僚が助けを求めて私に来ました。あるシステムでは、何の警告もなく一連のアラームが発生していることが判明しました。旧世代のマシンのメモリ使用量がしきい値を超えました。 1.1 まずはパフォーマンスを見る 旧世代のメモリ使用量 7 月中旬までは、メモリ使用量は比較的正常であり、各 GC で古い世代のオブジェクトの大部分をリサイクルできたことがわかります。 月の中旬以降、旧世代のメモリが徐々に増加し、解放できなくなります。明らかに、これはオブジェクトが正常にリサイクルされていないことが原因であるはずです。 メモリリーク〜 1.2 何をすべきか 新しく立ち上げたプロジェクトでこのような問題が発生した場合、影響は比較的小さいため、コードを直接ロールバックして出血を止めることが最優先となります。 しかし、このプロジェクトは明らかに何日もオンラインになっており、その間にどれだけの要求があったかは不明です。また、最近のトラフィックの増加により問題が発生しているため、トラフィックが顧客に開放されたことを意味します。 ロールバックは不可能なので、急いで問題を特定し、オンラインで修正してください。 パート2 位置決めの問題一般的な手順:
ただし、ダンプされたファイルは 10G を超えて大きすぎるため、MAT は基本的に無力であり、手動で分析するために印刷することしかできません。 2.1 問題コードを見つける jmap 結果ビュー 幸いなことに、異常な物体は非常に明白です。 Point オブジェクトと GeoDispLocal オブジェクトのインスタンスは数百万あります。まず、これら 2 つのオブジェクトがコード内でどのように使用されるかを見てみましょう。
それらはすべて現在のキャッシュ CacheMap に格納されており (メモリ リークの一般的な原因は、静的コレクションによって保持され、リサイクルできないことです)、ダンプ ファイル内の CacheMap.Entry も非常に高くなります。 CacheMap が最優先の容疑者です。まず、このキャッシュ クラスがどのようなものかを見てみましょう。
内部的には LRU 機能を備えたマップに依存します。どのように実装されますか?
内部的には、LinkedHashMap を使用して実装された LRU キャッシュです。コメントによると、容量制限があり拡張性のないMAPを構築するのが目的だそうです(Baiduで調べたらネット上の実装と全く同じですね~)。では、実際の状況は本当に想像通りなのでしょうか? 2.2 LinkedHashMap によって実装された LRUMap は便利ですか? 容量と拡張に関する設定を見てみましょう。なぜ設計者は LRUMap が拡張しないと考えるのでしょうか?
実際の使用法に応じてインスタンス化してみましょう。
LRU 条件関数がオーバーライドされるため、サイズが 6000 を超えると LRU 置換が実行されます。したがって、理論上、サイズが 8110 に達することはありません。 同時読み取り/書き込み競合を解決するにはどうすればよいでしょうか?
同時実行時の読み取り/書き込み競合を解決するために、設計者はクエリおよび変更メソッドにロックを追加しました。パフォーマンスを考慮するために、読み取り/書き込みロックが使用されました。つまり、読み取りロックは get 中に追加され、書き込みロックは put/remove 中に追加されました。 全体的な設計により、LRUMap の固定容量と同時操作の問題がうまく解決されているように見えますが、真実は何でしょうか? 実際、この問題はずっと以前から分析されてきました[1]。これは、LinkedHashMap が読み取り/読み取り操作を実行するときに、LRU を維持するために要素を変更するため、つまり、要素をリンク リストの末尾に移動するためです。これは読み取り書き込み同時実行の問題につながりますが、この説明は漠然とした感じがするので、これに基づいて読み取り書き込み同時実行の問題をより詳しく説明することにしました。 2.3 LinkedHashMap メモリリーク解析 読み取り/書き込みロックが追加されても機能しないのはなぜですか? ここでは、読み取り/書き込みロックの概念と適用可能なシナリオを明確にする必要があります。読み取り/書き込みロックを使用すると、複数のスレッドが読み取りロックを共有できるため、書き込みよりも読み取りが多い状況に適しています。 (読み取り操作によってストレージ構造が変更されないことが前提です) したがって、get 操作で問題が発生します。 LinkedHashMap の get 操作は、LRU 機能を実装するために書き直されます。取得後、現在のノードはリンク リストの末尾に移動されます。 さあ、同志たち、これは明らかに書き込み操作なので、読み取りロックを追加することはまだ役に立ちますか? つまり、複数のスレッドが入り込み、変更が行われると、どのような影響があるのでしょうか?同時実行の問題は発生しないでしょうか? 次に、ノード移動コードを比較して、マルチスレッドでの同時実行の問題を詳細に分析します。 最後に到達したらノードを移動する 実際の逆アセンブリ分析は次のとおりです。マルチスレッドの状況でメモリ リークが発生する理由は次のとおりです。 タイムスライスでのマルチスレッドの取得実行 スレッド 1 が最初の 2 つのステートメントを実行した後、タイム スライスを放棄したことがわかります。スレッド 2 が p.after=null を実行すると、タイム スライスが再度放棄されました。このように、a は次の <2,B> ノードになるはずでしたが、マルチスレッドでは null になりました。最終的に、次の 2 つのノードがリンク リストから除外され、削除操作がそれらに到達できず、メモリ リークが発生しました。 認証コードはここには掲載しません。ご興味がございましたら、ぜひご自身でお試しください。 パート3の要約問題が特定されたので、このメモリ リークをどのように修正すればよいでしょうか? 読み取り/書き込みロックはミューテックス ロックに変更できます。あるいは、分散ストレージを直接使用した場合、速度はどのくらい遅くなるのでしょうか?これは便利で簡単で、マシンのメモリを節約するために LRUMap を自分で構築する必要がありません。 すべてのエッセイは面接のためだけのものではなく、あらゆるオンラインの問題のトラブルシューティングの基礎となります。八本足のエッセイの役割を誤解しないでください。 。 。 この記事はWeChatの公開アカウント「Coder's Technical Journey」から転載したものです。以下のQRコードからフォローできます。この記事を転載する場合は、Coder’s Technology Road のパブリック アカウントにお問い合わせください。 |
>>: クラウドネイティブはクラウドコンピューティングの質的変化を促進し、デジタル変革への道を提供します
著者 |王 陸編集者 |王瑞平この記事は、Zhihu のクラウド ネイティブ アーキテクチャの責任者...
この世に愛とは何でしょう?それは、生死を問わず人々を結びつけるものです!すべては「愛」という言葉から...
Appleは今朝早く、iOS 9の正式版を世界中のユーザーに公開し、長い間待ち望んでいた多くのユーザ...
最近、20,000 を費やすと 120,000 の効果が得られる、3 分で 200,000 が入金さ...
uuuvpsは3年以上運営されています。公式が大量メールの形でプロモーション活動を発表するのはこれが...
愛は素晴らしく、至福のものです。誰もが情熱的な愛を望んでいるので、安定した関係を築くためには、多くの...
インターネット上での情報交換の加速により、さまざまなコンテンツを入手する時間が短縮され、あらゆる面で...
時々、私はいくつかのQQグループに引き込まれます。そこでは、服の組み合わせやショッピング体験について...
最近のBaiduのアルゴリズムの継続的な改善により、多くのウェブサイトが破壊されました。ほとんどのウ...
山を正面から見ると山頂が見えます。SEOも同じです!警察は赤警察と黒警察に分かれていますが、SEOも...
前回の記事では、「SEOについて:WeiboマーケティングにおけるSEOランキング」を書き、多くの友...
SaaS が 2021 年に入ると、風が再び強まります。資本市場の熱狂はそれ自体が物語っているが、そ...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています人をからか...
inceptionhosting は評判が良く、VPS 品質が保証されているサービス プロバイダーで...
2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています「一生懸命...