ノードのメモリ リークをトラブルシューティングするにはどうすればよいですか?次の記事は、ノードのメモリ リークのトラブルシューティング体験をまとめたもので、皆様のお役に立てれば幸いです。
Nodejs
サーバーサイド開発のシナリオでは、メモリ リーク
が間違いなく最も厄介な問題です。
しかし、プロジェクトが開発され反復され続ける限り、メモリ リーク
の問題は絶対に避けられず、遅かれ早かれ発生するだけです。したがって、効果的な メモリ リーク
トラブルシューティング方法を体系的に習得することは、Nodejs
エンジニアの最も基本的かつ中心的な能力です。
メモリ リークに対処する際の難しさは、無数の関数や関数の中から、どの行のどの関数や関数がメモリ リークの原因となっているのかを正確に特定する方法です。
残念ながら、現時点ではメモリ リークを簡単に特定できるツールは市場に存在しないため、この問題に初めて遭遇した多くのエンジニアは混乱し、対処方法がわからなくなるでしょう。
ここでは、22 年間に Memory Leak
を調査した事例に基づいて、私の対処方法を共有します。
問題の説明
2022 Q4
ある日、研究開発ユーザー グループから、当社の研究開発プラットフォームにアクセスできないことが報告され、多数のユーザーがバックグラウンドで例外が発生しました。タスクは完了していません。
最初の反応は、メモリ リークの可能性があるということです。幸いなことに、サービスはモニタリング (prometheus
grafana
) に接続されています。grafana
モニタリング パネルでは、 10.00 以降、メモリが制御不能になっていることが判明しました。明らかなデータ漏洩が発生しました。 [関連チュートリアルの推奨事項: nodejs ビデオ チュートリアル ]
メモリ リークの種類##手順 :
- プロセス メモリ
:
rss(常駐セット サイズ)、プロセスの常駐メモリ サイズ。
- heapTotal
: V8 ヒープの合計サイズ。
- heapused
: 使用される V8 ヒープのサイズ。
- external
: V8 オフヒープ メモリの使用量。
Nodejs
のグローバル メソッド
process.memoryUsage()を呼び出して、
heapTotalと # を含むこれらのデータを取得できます。 ##heapused
は V8 ヒープの使用量であり、Node.js
内の JavaScript オブジェクトが保存される場所です。また、external
は、C オブジェクトなど、非 V8 ヒープに割り当てられたメモリを表します。rss
は、プロセスの合計メモリ使用量です。一般に、監視データを確認するときは、heapused
インジケーターに注目してください。
メモリ リークは主に 2 つに分類されます。 into:
グローバル リーク- ローカル リーク
グローバル メモリ リーク
グローバル コンテンツ リークは通常、
ミドルウェア および コンポーネント
で発生します。このタイプのメモリ リークもトラブルシューティングが最も簡単です。 残念ながら、
で発生したメモリ リークはこのタイプに属さないため、ローカル リークの考え方に従って分析する必要があります。
このタイプの他の科学的分析方法については説明しませんが、この場合、二分法を使用するのが最も早いと思います。
プロセス フロー:
- 最初にコードの半分をコメントアウトします (半分に減らします
- ミドルウェア
,
コンポーネント
、または他の一般的なロジックの使用) インターフェイスを選択するか、ストレス テスト用の新しいテスト インターフェイスを作成します - Ifメモリリークが発生した場合、リークポイントは現在使用中のコード内にあり、リークがない場合、リークポイントは
- に表示され、上記のプロセスを約 20 回繰り返します~ 60 分。メモリ リークは確実に特定できます。
Nuxt## ベースの SSR アプリケーションを開発していたときのことです。 # では、オンラインにする前のストレス テストでアプリケーション メモリ リークが見つかり、グローバルであることが判明しました。予期せぬリークの後、二分法を使用して問題を特定するのに約 30 分かかりました。当時のリークの原因は、サーバー側で
永続的なメモリ リークの部分的なトラブルシューティングaxios
を使用していたためでしたが、その後、
axiosを統合し、関連するものをすべて
node- に置き換えました。 fetchで解決しました。それ以来、
axios PDSTに切り替えました。
axiosを
Nodeサービスで使用することはありません。
ほとんどのメモリ リークはローカル リークです。リーク ポイントは、特定の ミドルウェア
または特定の # に存在する可能性があります。 ##interface. 特定の 非同期タスク
では、このような特性により、トラブルシューティングも困難になります。この場合、分析のために heapdump
が実行されます。 <p>ここでは主にこの場合の私のアイデアについて話します。<code>heapdump
の詳細な説明は次の段落
Heap Dump
に記載します。 : ヒープ ダンプ。以下の部分はすべてheapdump
で表されます。heapdump
を実行するためのツールやチュートリアルは数多くあります (chrome、vscode、heapdump オープン ソース ライブラリなど)。私が使用するヒープダンプ ライブラリに関するオンライン チュートリアルは多数ありますが、ここでは説明しません。
ローカル メモリ リークのトラブルシューティングには、ある程度のメモリ リークのトラブルシューティングの経験が必要です。問題が発生するたびに、自分自身のテストとして扱ってください。経験を積んでから、メモリのトラブルシューティングを行うことができます。漏れの問題は後で発生しますが、それはますます速くなります。
1. メモリ リークが発生する時間範囲を特定する
これは非常に重要であり、これを知っておくと、調査の範囲が大幅に狭まる可能性があります。
この状況はよく発生します。この反復には 3 つの関数 A、B、C があり、ストレス テスト中またはオンラインになった後にメモリ リークが発生します。その後、直接ロックできるようになり、これら 3 つの新しい関数の間で小さなメモリ リークが発生します。この場合、heapdump
を実行するために運用環境に移動する必要はありません。いくつかのツールを使用してローカルでメモリ リーク ポイントを簡単に分析し、特定することができます。
2020 年の Q4
における特殊な状況により、メモリ リークが見つかったとき、メモリ リークが最初に発生した時期を特定することが困難でした。大まかに 1 でロックすることしかできません。数か月以内に。今月もメジャーバージョンアップを行っているのですが、これらの機能やインターフェースを一つ一つチェックしていくと、かなりのコストがかかってしまいます。
したがって、さらに分析するには、より多くのデータを組み合わせる必要があります
2. ヒープダンプ データを収集します
- 運用開始時
ノード
追加--expose-gc
、このパラメータはgc()
メソッドをグローバルに挿入して、GC の手動トリガーを容易にし、より正確なヒープ スナップショット
data ## を取得します。 # ここでは 2 つのインターフェイスを追加し、独自の排他的アクセス許可を取得しました。 - GC を手動でトリガーします
- #印刷ヒープ スナップショット
ヒープダンプ -
#プロジェクト開始後の初めてのスナップショット データの印刷
- メモリが 100M 増加した後: 最初に GC をトリガーし、次に 2 回目にヒープ スナップショット データを印刷します
- メモリがクリティカルに近づいています GC を再度トリガーして、ヒープ スナップショットを出力します
ヒープ スナップショット データを収集するときに特に注意が必要な点がいくつかあります。
ノード サービスは
heapdump中に中断されます。この時間は、その時点のサーバー メモリのサイズに応じて約 2 ~ 30 分になります。 。運用環境で
- heapdump
クリティカル ポイントでスナップショットを印刷するというのは、漠然とした説明ですが、試したことがある方ならわかると思いますが、メモリ スナップショットを印刷する前にクリティカル ポイントのすぐ近くで待機すると、印刷されません。したがって、この程度に近づくには自分をコントロールする必要があります。を実行するには、運用および保守と協力して合理的な戦略を策定する必要があります。ここでは、2 つのプライマリ
podとセカンダリ
podを使用します。プライマリ
podが停止すると、ビジネス リクエストは、本番稼働を確保するためにセカンダリ
podにロード バランシングされます。ビジネスの。 (このプロセスは運用保守と緊密に連携したプロセスである必要があります。結局のところ、
heapdumpもそれらを通じてサーバー内の
heap snapshotファイルを取得する必要があります)
- 少なくとも 3 回実行してください
- heapdump
(実際には、最も詳細なデータを取得するために 5 回実行しました)
3 . 分析のために監視パネルからのデータを結合します
監視にアクセスするにはアプリケーション サービスが必要です。ここでのアプリケーションは監視にprometheus
grafana を使用します。主にサービスの次の指標を監視します
- #QPS
- (1 秒あたりのリクエスト訪問数)、リクエストのステータス、およびそのアクセス パス
- (インターフェイスの平均応答時間) とそのアクセス データ
- バージョン
- (ハンドル)
# #イベント ループ ラグ
(イベント ラグ) サービス プロセスの再起動数
CPU 使用率- メモリ使用量:
- rss ,
- heapTotal
、
heapused、
external、
heapAvailableDetail
データのみが含まれません。十分です、heapdump
私の解析・処理結果データは非常に曖昧であり、視覚化ツールのサポートがあっても、問題を正確に特定することは困難です。今回は
grafanaのデータをいくつか組み合わせて見てみました。
当時のスナップショットデータが紛失してしまったので、ここでシーンをシミュレーションしてみます。
1.grafana
モニタリング インターフェイスを通じて、メモリが増加していて減少していないことがわかりますが、同時に の数が減少していることにも気づきました。サービス内のハンドル も急増していますが、落ちることはありません。
2. これは、リークが発生した月の新機能を確認し、メモリ リークは bull
メッセージ キュー コンポーネントの使用によって引き起こされているのではないかと疑ったときのことです。まず、関連するアプリケーション コードを分析しましたが、メモリ リークを引き起こすような問題があるとはわかりませんでした。
1.のハンドルリークの問題と合わせると、bull
を使用した後に特定のリソースを手動で解放する必要があるようですが、現時点では具体的な理由はわかりません。
3. 次に、5 回分の heapdunmp
データを分析し、そのデータを chrome
にインポートしました。5 回分のヒープ スナップショットを比較した結果、次のことがわかりました。各キューの作成後、 TCP 、 Socket 、 EventEmitter イベントは解放されません。現時点では、bull
の不規則な使用が原因であることはほぼ確実です。 bull
では、通常、キューは頻繁に作成されず、キューによって占有されているシステム リソースは自動的に解放されないため、必要に応じて手動で解放する必要があります。
#4. コードを調整した後、再度ストレス テストを実行したところ、問題は解決しました。
ヒント: Nodejs の
handle
は、基礎となるシステム リソース (ファイル、ネットワーク接続など) を指すポインターです。ハンドルを使用すると、Node.js プログラムは、基盤となるシステムと直接対話することなく、これらのリソースにアクセスして操作できるようになります。ハンドルは、Node.js ライブラリまたはモジュールで使用されるハンドルの種類に応じて、整数またはオブジェクトになります。 CommonHandle
:#ヒープダンプ分析の概要
- #fs.open()
返されるファイル ハンドル
- net.createServer()
返されるネットワーク サーバー ハンドル
- dgram.createSocket()
返された UDP ソケット ハンドル
- child_process.spawn()
#crypto.createHash()返された子プロセス ハンドル
- 返されたハッシュ ハンドル
zlib.createGzip()
- 返された圧縮ハンドル
通常、ヒープ スナップショット
データを初めて取得するときは、多くの人が混乱します。私も同様です。インターネット上で無数の分析テクニックを読み、それを私自身の実際の実践と組み合わせた後、さらに役立つテクニックをいくつかまとめました。一部の基本的な使用方法のチュートリアルについては、ここでは説明しません。ここでは、chrome;
概要ビュー
データをインポートした後の画像の見方について主に説明します。このビューでは、通常、まず [保持サイズ] を選択し、次にオブジェクトのサイズと数を観察します。経験豊富なエンジニアは、特定のオブジェクトの数が異常であることをすぐに判断できます。このビューでは、自分で定義したいくつかのオブジェクトを考慮することに加えて、
##ソケット
など、メモリ リークが発生しやすい一部のオブジェクトにも注意が必要です。 EventEmitter
グローバル
-
比較ビュー
合格した場合概要ビュー, 問題が特定できない場合は、通常、
Comparison ビューを使用します。このビューを通じて、2 つのヒープ スナップショット内のオブジェクトの数と、オブジェクトが占有するメモリの変化を比較できます。
この情報を通じて、ヒープ内のオブジェクトの値を判断し、一定の操作 (特定の操作) 後のメモリの変化を判断することができ、これらの値を通じて異常なオブジェクトを見つけることができます。これらのオブジェクトの名前属性または関数によって、メモリ リーク調査の範囲が狭まる可能性があります。 [
比較
] ビューで 2 つのヒープ スナップショットを選択し、それらを比較します。 2 つのヒープ スナップショット間でどのオブジェクトが追加されたか、2 つのヒープ スナップショット間でどのオブジェクトが削減されたか、どのオブジェクトのサイズが変更されたかを確認できます。
ビューでは、オブジェクト間の関係だけでなく、タイプ、サイズ、参照カウントなどのオブジェクトの詳細も表示できます。この情報により、どのオブジェクトがメモリ リークの原因となっているかを理解できます。
#統計ビュー
この図は非常に単純なので、詳細については説明しません
メモリ リークのシナリオ
- グローバル変数: グローバル変数はリサイクルされません
- キャッシュ: 次のようなメモリ集約型のサードパーティ ライブラリが使用されます
lru-cache
保存しすぎるとメモリ不足になります。Nodejs サービスでは lru-cache
の代わりに redis- を使用することをお勧めします。ハンドル リーク: システム リソースは呼び出し後に解放されません
- イベント モニタリング
- 終了
- 循環参照
概要
問題の種類を初めて特定しやすくするために、サービスにはアクセス監視が必要です
-
メモリ リークがグローバルかローカルかを判断します
二分法を使用して、グローバル メモリ リークのトラブルシューティングを迅速に行い、特定します。
-
ローカル メモリ リーク
- メモリ リークが発生し、問題を迅速に特定します。 機能
- ヒープ スナップショット データを少なくとも 3 回収集します。
- 監視データ、ヒープ スナップショット データ、リーク発生時の新しい関数を組み合わせて、問題を特定します。メモリ リーク ポイント
メモリ リークの問題が発生しても恐れることはありません。メモリ リークの問題のトラブルシューティングでより多くの経験を積んでください。処理の経験が増えるほど、メモリ リークの問題は、すぐに見つけやすくなります。各解決策の後で、レビューと要約を実行し、もう一度振り返りますヒープ スナップショット
データは、関連するエクスペリエンスをより速く蓄積するのに役立ちます
その他
- ストレス テスト ツール: wrk
lru-cache
保存しすぎるとメモリ不足になります。Nodejs サービスでは lru-cache
の代わりに 問題の種類を初めて特定しやすくするために、サービスにはアクセス監視が必要です
メモリ リークがグローバルかローカルかを判断します
二分法を使用して、グローバル メモリ リークのトラブルシューティングを迅速に行い、特定します。
ローカル メモリ リーク
- メモリ リークが発生し、問題を迅速に特定します。 機能
- ヒープ スナップショット データを少なくとも 3 回収集します。
- 監視データ、ヒープ スナップショット データ、リーク発生時の新しい関数を組み合わせて、問題を特定します。メモリ リーク ポイント
メモリ リークの問題が発生しても恐れることはありません。メモリ リークの問題のトラブルシューティングでより多くの経験を積んでください。処理の経験が増えるほど、メモリ リークの問題は、すぐに見つけやすくなります。各解決策の後で、レビューと要約を実行し、もう一度振り返りますヒープ スナップショット
データは、関連するエクスペリエンスをより速く蓄積するのに役立ちます
ノード関連の知識については、nodejs チュートリアルを参照してください。
以上が【体験談まとめ】Nodeのメモリリークのトラブルシューティング方法は?アイデアを共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

WebStorm Mac版
便利なJavaScript開発ツール

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター
