問題
New Relic Node.js エージェントをインストールしたところ、Node.js アプリケーションのメモリ使用量が増加しました。
解決
このメモリの増加にはいくつかの原因が考えられ、それぞれに解決策があります。
Node.js は Cluster モジュールを提供します。これにより、ホストで使用可能なすべてのプロセッサ コアを使用して、要求を並行して処理できます。ただし、各クラスター ワーカーは SSL トランザクション用に独自のスラブ バッファーを割り当て、Node.js エージェント データの独自のコピーを保持します。これにより、使用されるクラスター ワーカーの数によってメモリ オーバーヘッドが乗算されます。これは、ホストが複数の Node.js アプリケーションを同時に実行する場合にも当てはまります。
Solution:
クラウドサービスプロバイダーの中には、実際に使用できるプロセッサコア数よりも多くのプロセッサコアを使用する環境を使用しているところがあります。クラスターワーカーの数を減らしたり、クラスターのサポートを受けずに動作させたりすることで、パフォーマンスに影響を与えることなくメモリ使用量を減らすことができます。
ログメッセージはデフォルトでディスクに記録されます。 メッセージ データの処理方法により、メッセージ オブジェクトはガベージ コレクションのためにOld-pointer-spaceに移動される場合があります。 つまり、オブジェクトへの参照がすべてなくなった後でも、オブジェクトはしばらくメモリ内に残ります。 これにより、特定の時点でプロセスによって消費されるメモリの量が増大します。 ガベージコレクションにも追加の処理時間が使用されます。
Solution:
Node.js のバージョンによっては、エージェントがデフォルトでtrace
またはinfo
ログ レベルになる場合があります。ロギングの詳細度をinfo
またはwarn
レベルに下げて、メモリ使用量とガベージ コレクションに費やされる時間を大幅に減らします。
多くのデータベース ドライバは、 cursor
と呼ばれる抽象化を使用します。 カーソルは、クエリの結果を反復処理する機能を提供します。 たとえば、 mongodbドライバーは、 find
クエリを実行するときにカーソルを提供します。
カーソルは、Node.js ランタイムではオブジェクトとして、MongoDB サーバーではエンティティとして存在します。アプリケーションがcursor
の使用を終了したら、それを閉じて、サーバー アプリケーションとクライアント アプリケーションの両方でリソースを解放する必要があります。
Node.js では、サーバーでcursor
を閉じることなく、カーソルをガベージ コレクションしてアプリケーションのリソースを解放することができます。これは、アプリケーションでは見過ごされる可能性があります。ただし、New Relic Node.js エージェントは開いているカーソルを追跡して、結果の反復処理に費やされた時間を測定します。アプリケーションが使用するすべてのカーソルを閉じない場合、エージェントは引き続き古いカーソルを追跡し、メモリ リークを引き起こします。
Solution:
アプリケーションがクエリの結果の処理を終了した後、 cursor.close()
を呼び出して、アプリケーションで作成されたすべてのcursor
が閉じられていることを確認します。
Node.jsエージェントは、アプリが処理する各トランザクションのデータを記録します。データは通常、トランザクション名でグループ化されます。エージェントが使用するメモリは、1分ごとの収穫サイクルで記録される異なるトランザクションの数に応じて増加します。
また、各トランザクションの間、より多くのデータが保持されますが、最終的にはトランザクションの完了時に破棄されます。エージェントが使用するメモリは、アプリケーションが処理する同時トランザクションの数に応じて増加します。
Solution:
エージェントデータストレージがメモリ使用量の増加の原因であると判明した場合、ホストにメモリを追加するか、より大きなクラウドインスタンスに変更することで対処できます。