序文これは、オンライン コンテナーの拡張によって発生した調査です。最終的には、実際の OOM が原因ではないことが判明しましたが、調査のプロセスを要約して記録しました。プロセス全体は、段階的に手がかりを探し、段階的に結果を検証する、事件解決のようでした。 私個人としては、これを行うことの意義と必要性にはいくつかの側面があると考えています。
環境: Tencent Taf プラットフォーム上で実行される NodeJs サービス。 問題の原因最初は、タイミング関数が起動された後、オンラインコンテナが自動的に拡張されたためでした。NodeJsサービス自体はいくつかのインターフェースクエリとsocket.io関数のみであり、大きなトラフィックや高い同時実行性はないため、実際にはサービスは8つのコンテナに拡張する必要があります(1つのコンテナに2Gのメモリが割り当てられます)。これを考えると、メモリリークを疑いました。同時に、ログにメモリ不足が表示されることもあります。 拡大の理由 運用保守担当者に問い合わせたところ、メモリ使用量が限界値に達したことが原因であることが判明しました。 負荷条件 まず、メモリ使用量の増加が過度のサービス負荷によって引き起こされている可能性を排除する必要があります。これは通常のビジネス現象である可能性があります。 監視を通じて、トラフィックと CPU 使用率はそれほど高くなく、非常に低いとさえ言えることがわかりました。したがって、このような高いメモリ使用量は異常な現象です。 これはメモリの問題によって発生し、徐々に継続的に増加する現象があるため、メモリ リークと考えられます。一般的な方法は、「ヒープ スナップショット」または heapsnapshot ファイルを印刷することです。 コンテナを入力します:
NodeJsプロジェクトフォルダに入る
スナップショットを生成します。 定数ヒープダンプ = require('ヒープダンプ'); heapdump.writeSnapshot('./' + new Date().getTime() + '.heapsnapshot', 関数(err, ファイル名) { console.log('ダンプが書き込まれました', ファイル名); }); lrzsz コマンドを使用してコンテナ内のファイルを直接転送すると速度が遅いため、scp コマンドを使用して静的リソース サーバーに転送し、ブラウザーからダウンロードする必要があります。
ヒープスナップショットを比較するサービスを起動して一定時間実行すると 2 つのスナップショットが生成され、比較すると Websocket Socket などのキーワードのみが大まかに確認できます。 さらに拡大しても、それが特定の機能によって引き起こされたかどうかはわかりません。 スナップショットには手がかりがないようです。プロジェクト全体の業務コードはそれほど大きくないので、1行ずつレビューしましたが、OOMの原因となるような異常な記述はないようです。実際、業務コードが小さければ問題ありません。大規模なプロジェクトの場合、このアプローチは費用対効果が低く、直接コードレビューに行くのではなく、何らかの診断方法を使用して確認する必要があります。 スナップショットを数回印刷し、数回読み取った後でも、「websocket」という単語が表示されたので、問題はソケット リンクが解放されていないことが原因ではないかと考えました。 Google で WebSocket メモリ リークを検索したところ、実際に存在することがわかりました。解決策は、perMessageDeflate を追加して圧縮を無効にすることです。現在、socket-io の下位バージョンがデフォルトで有効になっているため、それを追加してしばらくメモリ使用量を観察しましたが、明らかな低下はありませんでした。リリース後もメモリ使用量は非常に高かった。 設定構文:
クライアントから送信されたリクエストには次のフィールドが含まれます。 まず、このパラメータはデータを圧縮するために使用されます。クライアント側ではデフォルトで有効になっており、サーバー側では無効になっています。何らかの理由で、これを有効にするとメモリとパフォーマンスが消費されます。有効にするかどうかを決定する前に、これを考慮することが公式の推奨事項です。ただし、バージョン ^2.3.0 などの socket-io の下位バージョンは有効になっています (これはバグのようで、以降のバージョンではデフォルトで閉じるように変更されています)。 この拡張機能は、サーバーではデフォルトで無効になっており、クライアントではデフォルトで有効になっています。これにより、パフォーマンスとメモリ消費の面で大きなオーバーヘッドが追加されるため、本当に必要な場合にのみ有効にすることをお勧めします。 https://github.com/socketio/socket.io/issues/3477#issuecomment-610265035 電源を入れた後もメモリ使用量は高いままです。 コンソールログ もう 1 つの現象は、既存の Node サービスがログを出力することです。インターネットで NodeJs のメモリ リークに関する記事をいくつか調べたところ、コンソール ログ出力によってリークが発生していることがわかりました。そこで、コンソールをコメント アウトして、メモリ使用量の監視を続けました。結果は、依然としてメモリ使用量が高くなっていました。 手がかりはここで終わっているようで、手がかりは何もありません。 ログ 翌日、偶然ログ ファイルを見ました。サービスの開始時にいくつかの起動ログが印刷されるため、出力が重複していることがわかりました。 これは、システムが繰り返し実行されていることを示しています。この仮説を確認するには、top コマンドを使用して結果を表示します。 TOPコマンド 同時に、具体的なメモリ使用量も確認したいと思います。ワーカープロセスが非常に多いことがわかりました。現在の業務の実際の使用状況からすると、2〜4 個で十分ではないでしょうか。なぜこれほど多くの子プロセスを開く必要があるのでしょうか。 PID ユーザー PR NI 仮想リソース SHR S %CPU %MEM 時間+ コマンド 90359 ユーザー名 20 0 736m 38m 14m S 0.0 0.0 0:07.30 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90346 ユーザー名 20 0 864m 38m 14m S 0.3 0.0 0:07.08 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90381 ユーザー名 20 0 730m 38m 14m S 0.3 0.0 0:08.75 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90366 ユーザー名 20 0 804m 37m 14m S 0.0 0.0 0:06.94 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90618 ユーザー名 20 0 730m 37m 14m S 0.0 0.0 0:08.42 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90326 ユーザー名 20 0 736m 37m 14m S 0.0 0.0 0:08.46 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90542 ユーザー名 20 0 736m 37m 14m S 0.0 0.0 0:08.85 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90332 ユーザー名 20 0 799m 37m 14m S 0.0 0.0 0:07.32 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90580 ユーザー名 20 0 732m 37m 14m S 0.3 0.0 0:08.94 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90602 ユーザー名 20 0 731m 37m 14m S 0.3 0.0 0:08.33 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90587 ユーザー名 20 0 735m 37m 14m S 0.0 0.0 0:08.83 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90568 ユーザー名 20 0 731m 37m 14m S 0.0 0.0 0:08.83 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90544 ユーザー名 20 0 729m 37m 14m S 0.0 0.0 0:09.07 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90556 ユーザー名 20 0 729m 37m 14m S 0.0 0.0 0:08.82 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90431 ユーザー名 20 0 735m 37m 14m S 0.0 0.0 0:08.29 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90486 ユーザー名 20 0 729m 37m 14m S 0.0 0.0 0:09.06 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90516 ユーザー名 20 0 735m 37m 14m S 0.0 0.0 0:08.95 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90465 ユーザー名 20 0 729m 37m 14m S 0.0 0.0 0:09.06 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90527 ユーザー名 20 0 735m 37m 14m S 0.0 0.0 0:08.46 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90487 ユーザー名 20 0 732m 37m 14m S 0.3 0.0 0:08.48 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90371 ユーザー名 20 0 731m 37m 14m S 0.3 0.0 0:08.75 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90423 ユーザー名 20 0 729m 36m 14m S 0.3 0.0 0:08.09 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90402 ユーザー名 20 0 729m 36m 14m S 0.3 0.0 0:08.96 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90500 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:08.70 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90353 ユーザー名 20 0 729m 36m 14m S 0.3 0.0 0:08.95 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90636 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:08.84 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90425 ユーザー名 20 0 732m 36m 14m S 0.0 0.0 0:08.78 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90506 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:08.84 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90589 ユーザー名 20 0 729m 36m 14m S 0.3 0.0 0:09.05 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90595 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:09.03 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90450 ユーザー名 20 0 729m 36m 14m S 0.3 0.0 0:08.97 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90531 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:08.99 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90509 ユーザー名 20 0 735m 36m 14m S 0.0 0.0 0:08.67 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90612 ユーザー名 20 0 730m 36m 14m S 0.3 0.0 0:08.84 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90479 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:08.58 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90609 ユーザー名 20 0 731m 36m 14m S 0.3 0.0 0:09.23 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90404 ユーザー名 20 0 734m 36m 14m S 0.3 0.0 0:08.78 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90395 ユーザー名 20 0 736m 36m 14m S 0.0 0.0 0:08.57 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90444 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:09.04 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90438 ユーザー名 20 0 729m 36m 14m S 0.3 0.0 0:07.78 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90340 ユーザー名 20 0 736m 36m 14m S 0.3 0.0 0:07.37 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90333 ユーザー名 20 0 729m 36m 14m S 0.0 0.0 0:07.60 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90563 ユーザー名 20 0 735m 36m 14m S 0.3 0.0 0:08.93 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90565 ユーザー名 20 0 734m 36m 14m S 0.3 0.0 0:08.77 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90457 ユーザー名 20 0 735m 36m 14m S 0.0 0.0 0:08.31 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90387 ユーザー名 20 0 740m 36m 14m S 0.0 0.0 0:07.59 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90573 ユーザー名 20 0 728m 35m 14m S 0.0 0.0 0:09.06 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90472 ユーザー名 20 0 728m 35m 14m S 0.0 0.0 0:08.94 /usr/local/app/service_name/bin/src/index.js: ワーカープロセス 90313 ユーザー名 20 0 588m 27m 13m S 0.0 0.0 0:00.46 /usr/local/app/service_name/bin/src/index.js: マスタープロセス %MEM 列の値はコンテナ内の特定のメモリ使用量を示しておらず、常に 0.0 と表示されるため、VIRT、RES、SHR の値を確認する必要があります。これらの意味については、https://www.orchome.com/298 を参照してください。 RES の方が重要です。RES は、物理メモリ空間にマップされているプロセス仮想メモリ空間の部分のサイズを指します。したがって、ワーカー プロセスは 35 ~ 38M のメモリ サイズを占有していることがわかります。ワーカー プロセスは 48 個、マスター プロセスは 1 個あります。 48 個のワーカー プロセスはどのようにして発生したのでしょうか? CPU の論理数を照会すると、実際には 48 個あることがわかります。 # コアの合計数 = 物理 CPU の数 x 物理 CPU あたりのコアの数 # 論理 CPU の合計数 = 物理 CPU の数 x 物理 CPU あたりのコアの数 x ハイパースレッドの数 # 物理 CPU の数を表示します cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l # 各物理CPUのコア数(コア数)を表示します cat /proc/cpuinfo| grep "CPU コア"| uniq # 論理 CPU の数を表示します cat /proc/cpuinfo | grep "processor" | wc -l プロセス数を制御する 私は Taf プラットフォームにあまり詳しくないので、NodeJS を taf で実行するには、対応するパッケージ @tars/node-agent が必要であることを知りました。公式 Web サイトの使用法ドキュメントを確認しました: https://tarscloud.github.io/TarsDocs/dev/tars.js/tars-node-agent.html -i設定があり、これはインスタンスを表します -i, --インスタンス node-agent は、Node.js ネイティブ Cluster モジュールを使用して負荷分散を実現します。 ここで、ノードエージェントによって開始されるサブプロセス (ビジネス プロセス) の数を設定できます。 設定されていない場合(または auto または 0 に設定されている場合)、開始される子プロセスの数は CPU 物理コアの数と同じになります。 max に設定すると、開始される子プロセスの数は CPU (すべてのコア) の数と等しくなります。 tarsnode によってノードエージェントが起動されると、TARS 構成ファイルの tars.application.client.asyncthread 構成セクションが自動的に読み取られます。 また、TARS プラットフォーム -> サービスの編集 -> 非同期スレッドの数から調整することもできます。 https://tarscloud.github.io/TarsDocs/dev/tars.js/tars-node-agent.html 「プライベート テンプレート」で設定を変更できます。 次に、サービスを再起動してメモリ使用量を確認します。 ワーカー プロセスの数がメモリ使用量に影響していることがわかります。元のメモリ使用量の傾向グラフは増加し続けます (これが、最初にメモリ リークを疑った理由です)。この問題は、ワーカー プロセスの数を減らした後には現れませんでした。今は無視して、後で引き続き観察します。 重複したコンソールとワーカー プロセスの関係を確認するために、2 つのワーカー プロセスを開始してログを確認したところ、ログが実際に 2 回印刷されていることが分かりました。 要約するこの問題を見直してみましょう: なぜ間に合わずに発見されなかったのでしょうか? これは、バックエンド サービスの一部の機能にあまり敏感ではないフロントエンド開発者の役割に関連している可能性があります。私はそれに全く注意を払っていません、あるいはそれを知らないか理解していません。 事前に回避することはできますか? Node サービスのメモリが増加傾向にあることを通知する同様のアラーム メカニズムが存在する可能性があります。私はまだ Taf プラットフォームの機能に精通していないため、後で調べてみます。 NodeJs での高メモリ使用量のトラブルシューティングに関するこの記事はこれで終わりです。NodeJs での高メモリ使用量の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Linux でタスク用のカスタム システム トレイ インジケーターを作成する
>>: MySql 8.0.11 のインストールと設定のチュートリアル
問題を見つける最近、以前のデータを入力していたときに、プログラムが突然次のエラーを報告しました。 [...
目次js の1. グローバルガードを登録する2. Vuex 状態管理グローバルキャッシュルート3. ...
目次序文クイックレビュー: JavaScript 関数関数とは何ですか?関数を宣言する関数の呼び出し...
最近はWeb2.0という言葉をよく耳にしますが、Web2.0とは何でしょうか? Web 1.0 とど...
序文Vue で要素を初回取得できない問題の解決方法は、ポップアップ ウィンドウで要素を取得するために...
導入Redis を詳しく説明する必要はありません。インストールと設定を始めましょう。インストールソー...
ブラウザでのページのレンダリング時間をできるだけ短縮するにはどうすればよいでしょうか? この記事は、...
目次MySQL 複数インスタンスマルチインスタンスの概要マルチインスタンスとは何ですか?複数のインス...
目次1. 連結() 2. 結合() 3. プッシュ() 5. シフト() 6. シフト解除() 7....
目次1. 双方向データバインディングとは1. データの双方向バインディングを実装する必要があるのはな...
問題を見つける最近、MySQL コマンドを使用して MySQL サーバーに接続したときに、以下のよう...
目次背景1. dns-prefetch とは何ですか? 2. dns-prefetch を設定するに...
目次背景1. 文書の説明2. 特定の用途結論背景ここで、状況について説明しましょう。親コンポーネント...
ステップ1: 現在のカーネルを表示する 読み取る $ uname -a Linux rew 4.15...
この記事では、例を使用して、MySQL 累積集計の原理と使用方法を説明します。ご参考までに、詳細は以...