最近、nodejs モニタリングについて勉強していますが、簡単なバージョンのモニタリングを書くことを学ぶエネルギーはありませんが、それでもこれらのインジケーターを取得する方法を学ばずにはいられません (多くの情報を調べた後、そう感じています)。国内のインターネット上ではこの内容の紹介が少ないので、サーバーノードのナレッジポイントも整理中ですので、この記事にまとめて共有させていただきます。
この記事の一部のインジケーターには問題がある可能性があります。実際、これらのデータを整理してモニタリング ライブラリに書き込み、独自の中小規模のプロジェクトで使用できます。そして、フロントエンドの React には bizcharts や g2 などのツールがあり、フロントエンド自体が大きな画面のデータを描画します。エッセイモニターによって収集されたデータの次元は、私たちのものほど包括的ではないと思います。
通常、サーバーのパフォーマンスのボトルネックは次のとおりです。CPU
どちらもマシンの混雑度をある程度反映します。
CPU 使用率は、実行中のプログラムによって占有される CPU リソースであり、特定の時点でマシンがプログラムをどのように実行しているかを示します。使用率が高いほど、その時点でマシンが多くのプログラムを実行していることを意味し、その逆も同様です。使用率のレベルは CPU の強度に直接関係します。まず、CPU 使用率を取得するコードを理解するために、関連する API といくつかの用語の説明を理解しましょう。
os.cpus()
各論理 CPU コアに関する情報を含むオブジェクトの配列を返します。
モデル: CPU コアのモデルを指定する文字列。
速度: CPU コアの速度を MHz で指定する数値。
回:次のプロパティを含むオブジェクト:
注: nice
値は POSIX のみに適用されます。 Windows オペレーティング システムでは、 nice
の値はすべてのプロセッサで常に 0 です。
ユーザーや素敵なフィールドを見て、利点について混乱する学生もいますが、私も同様です。そのため、その意味を注意深く尋ねました。続けてください。
user は、CPU がユーザー モードで実行されている時間の割合を示します。
アプリケーションプロセスの実行は、ユーザーモードとカーネルモードに分割されます。CPUは、通常、論理モードまたは数値計算で、通常、カーネルモードで開始されたシステムコールを実行します。プロセスのリソース要求に応じて。
ユーザー空間プログラムは、カーネルの一部ではないプロセスです。シェル、コンパイラー、データベース、Web サーバー、およびデスクトップ関連プログラムはすべてユーザー空間のプロセスです。 プロセッサがアイドル状態ではない場合、CPU 時間のほとんどがユーザー空間プロセスの実行に費やされるのが通常です。
Nice は、CPU が低優先度のユーザー モードで実行される時間の割合を表します。低優先度は、プロセスの nice 値が 0 未満であることを意味します。
user は、CPU がカーネル モードで実行される時間の割合を表します。
一般に、アプリケーション プロセスが多数のシステム コールを開始しない限り、カーネル モードのCPU 使用率が高くなりすぎることはありません。この値が高すぎる場合は、頻繁な IO 操作など、システム コールに時間がかかることを意味します。
idle は、CPU が実行するタスクがないアイドル状態にある時間の割合を示します。
irq は、CPU がハードウェア割り込みを処理する時間の割合を表します。
ネットワーク カードの割り込みはその典型的な例です。ネットワーク カードはデータ パケットを受信した後、ハードウェア割り込みを通じて CPU に処理を通知します。 システムのネットワーク トラフィックが非常に多い場合、IRQ 使用量の大幅な増加が観察される可能性があります。
ユーザーの状態が 70% 未満、カーネルの状態が 35% 未満、全体の状態が 70% 未満の場合、正常な状態としてカウントできます。
次の例は、Node.js での os.cpus() メソッドの使用を示しています。
例 1:
// を示す Node.js プログラム //os.cpus()メソッド // OSモジュールの割り当て const os = require('os'); // os.cpus() 値を出力します console.log(os.cpus());
出力:
[ { モデル:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz', 速度:2712、 回: { ユーザー:900000、素敵:0、sys:940265、アイドル:11928546、irq:147046 } }、 { モデル:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz', 速度:2712、 回: { ユーザー:860875、素敵:0、sys:507093、アイドル:12400500、irq:27062 } }、 { モデル:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz', 速度:2712、 回: { ユーザー:1273421、素敵:0、sys:618765、アイドル:11876281、irq:13125 } }、 { モデル:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz', 速度:2712、 回: { user:943921, nice:0, sys:460109, idle:12364453, irq:12437 } } ]
以下は、CPU 使用率を取得する方法のコードです。
const os = require('os'); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); クラス OSUtils { コンストラクター() { this.cpuUsageMSDefault = 1000; //CPU 使用率のデフォルト期間} /** * 一定期間の CPU 使用率を取得します* @param { Number } Options.ms [期間、デフォルトは 1000ms、つまり 1 秒] * @param { Boolean } Options.percentage [true (パーセントの結果として返される) | false] * @returns {約束} */ async getCPUUsage(options={}) { const that = this; let { cpuUsageMS, 割合 } = オプション; cpuUsageMS = cpuUsageMS || その.cpuUsageMSDefault; const t1 = that._getCPUInfo(); // t1 時点の CPU 情報 await sleep(cpuUsageMS); const t2 = that._getCPUInfo(); // t2 時点の CPU 情報 const idle = t2.idle - t1.idle; const total = t2.total - t1.total; 使用量 = 1 - アイドル / 合計とします。 if (パーセント) 使用量 = (使用量 * 100.0).toFixed(2) + "%"; 使用法を返す。 } /** * CPU 瞬間時間情報の取得 * @returns { Object } CPU 情報 * user <number> CPU がユーザー モードで費やしたミリ秒数。 * nice <number> CPU が nice モードで費やすミリ秒数。 * sys <数値> CPU がシステム モードで費やしたミリ秒数。 * idle <数値> CPU がアイドル モードで費やしたミリ秒数。 * irq <数値> CPU が割り込み要求モードで費やしたミリ秒数。 */ _getCPUInfo() { const cpus = os.cpus(); ユーザー = 0、ナイス = 0、sys = 0、アイドル = 0、irq = 0、合計 = 0 とします。 for (CPU を CPU に入れる) { const 時間 = cpus[cpu].times; ユーザー += 回.ユーザー; 素敵 += 回。素敵; sys += 回.sys; アイドル += 回.アイドル; irq += 回.irq; } 合計 += ユーザー + ナイス + システム + アイドル + irq; 戻る { ユーザー、 システム、 アイドル、 合計、 } } } const cpuUsage = new OSUtils().getCPUUsage({ パーセント: true }); console.log('cpuUsage: ', cpuUsage.then(data=>console.log(data))); // 私のコンピュータの
。CPU 負荷 (loadavg) は、特定の負荷を指します。 CPU 時間を占有しているプロセスと CPU 時間を待機しているプロセスの数は、負荷平均です。ここでの CPU 時間を待機しているプロセスとは、待機状態のプロセスを除いた、起動を待っているプロセスを指します。
その前に、ノード API
os.loadavg()
が 1、5、15 分の平均負荷を含む配列を返すことを学習する必要があります。
負荷平均は、オペレーティング システムによって計算され、小数として表されるシステム アクティビティの尺度です。
負荷平均は Unix 固有の概念です。 Windows では、戻り値は常に[0, 0, 0]
これは、オペレーティング システムの現在のビジー状態を表すために使用されます。これは、CPU が使用中であり、使用を待機しているタスクの平均数として単純に理解できます。単位時間あたりの CPU。 CPU 負荷が高すぎることは、Node にプロセスが多すぎることを示しており、紫禁城モジュールを使用して新しいプロセスを繰り返し開始することに反映されている可能性があります。
const os = require('os'); //CPU スレッドの数 const length = os.cpus().length; //シングルコア CPU の平均負荷は、1、5、15 分の平均負荷を含む配列を返します os.loadavg().map(load =>load / length);
まず API について説明します
そうしないと読み取れません。 メモリ インジケーターを取得するためのコードを理解してください。
この関数は 4 つのパラメーターを返します。意味と違いは次のとおりです。
次のコードを使用して、子プロセスのメモリ使用量を出力します。rss が top コマンドの RES とほぼ等しいことがわかります。また、メインプロセスのメモリはわずか 33M であり、子プロセスのメモリ使用量よりも小さいことがわかります。
var showMem = function(){ var mem = process.memoryUsage(); var format = 関数(バイト){ return (バイト / 1024 / 1024).toFixed(2) + 'MB'; }; console.log('プロセス: heapTotal ' + format(mem.heapTotal) + ' heapused ' + format(mem.heapused) + ' rss ' + format(mem.rss) + ' external:' + format(mem.external) ); console.log('------------------------------------------ --- ---------------');Node の場合
、
メモリ リークが発生すると、トラブルシューティングはそれほど簡単ではありません。メモリが増加するだけで減少しないことが監視されている場合は、メモリ リークの問題があるはずです。健全なメモリ使用量は増減するはずです。アクセスが多い場合は増加し、アクセスが減少すると
const os = require('os'); // 現在のノードのプロセスのメモリ使用量を確認します const { rss, heapused, heapTotal } = process.memoryUsage(); // システム空きメモリを取得 const systemFree = os.freemem(); // システム メモリの合計を取得します const systemTotal = os.totalmem(); module.exports = { メモリ: () => { 戻る { system: 1 - systemFree / systemTotal, // システム メモリ使用量 heap: heapused / headTotal, // 現在のノードのプロセス メモリ使用量ノード: rss / systemTotal, // 現在のノードのプロセス メモリ使用量のシステム メモリの割合} } }
ディスク監視は主にディスク使用量を監視します。ログの書き込みが頻繁に行われるため、ディスク容量が徐々に消費されていきます。ディスクが不足すると、システムにさまざまな問題が発生します。给磁盘的使用量设置一个上限,一旦磁盘用量超过警戒值,服务器的管理者就应该整理日志或者清理磁盘。
次のコードは、Easy Monitor 3.0 を参照しています。
const { execSync } = require('child_process'); const result = execSync('df -P', {エンコーディング: 'utf8'}) const 行 = result.split('n'); const メトリック = {}; Lines.forEach(line => { if (line.startsWith('/')) { const match = line.match(/(d+)%s+(/.*$)/); if (一致) { const rate = parseInt(match[1] || 0); const マウント = match[2]; if (!mounted.startsWith('/ Volumes/') && !mounted.startsWith('/private/')) { メトリック[マウント] = レート; } } } }); console.log(metric)
I/O 負荷は主にディスク I/O を指します。これは、主にネットワークサービス用に記述されたアプリケーションの読み取りと書き込みの状況を反映しています。 。
I/O インジケーターを取得するには、iostat という Linux コマンドを理解する必要があります。これがインストールされていない場合は、このコマンドが I/O インジケーター
iostat -dx を反映できる理由を見てみましょう。
プロパティの説明
rrqm/s: 1 秒あたりのマージ読み取り操作の数。つまり、rmerge/s (デバイスへの読み取りリクエストが 1 秒あたりにマージされる回数。ファイル システムは同じブロックを読み取るリクエストをマージします) wrqm/s: 1 秒あたりのマージ書き込み操作の数。つまり、wmerge/s (デバイスへの書き込みリクエストが 1 秒あたりにマージされる回数) r/s: 1 秒あたりに完了した I/O デバイスからの読み取り数。それがリオ/スです w/s: 1 秒あたりに完了した I/O デバイスへの書き込み数。それはwio/sです rsec/s: 1 秒あたりに読み取られるセクター数。それは rsect/s です wsec/s: 1 秒あたりに書き込まれるセクター数。つまり、wsect/s rkB/s: 1 秒あたりの読み取り K バイト。各セクターのサイズは 512 バイトであるため、これは rsect/s の半分になります。 wkB/s: 1 秒あたりに書き込まれる K バイト数。これは wsect/s の半分です。 avgrq-sz: デバイス I/O 操作あたりの平均データ サイズ (セクター)。 avgqu-sz: I/O キューの平均長。 await: 各デバイス I/O 操作の平均待機時間 (ミリ秒)。 SVCTM:各デバイスI/O操作の平均処理時間(ミリ秒)。 %util: 1 秒のうち何パーセントが I/O 操作に使用されているか、つまり、
%util が 100% に近い場合は、I/O 操作が多すぎることを意味します
。
/O リクエストが生成されます。I /O システムは完全にロードされており、このディスクにボトルネックがある可能性があります。
If await is much larger than svctm, it means that the I/O queue is too long and the response time of the application becomes slower. If the response time exceeds the range that the user can tolerate, you can consider replacing a faster disk,カーネル エレベーター アルゴリズムを調整し、アプリケーションを最適化するか、CPU をアップグレードします。
nodejsのページ応答時間は、教師liao xuefengのブログ記事から選択されています。
最近、Nodejs のパフォーマンスを監視したいと思っています。ログを記録して分析するのは非常に面倒です。最も簡単な方法は、各 HTTP リクエストの処理時間を記録し、それを HTTP レスポンス ヘッダーで直接返すことです。
HTTP リクエストの時刻の記録は非常に簡単です。つまり、リクエストを受信したときにタイムスタンプを記録し、リクエストに応答したときに別のタイムスタンプを記録します。その差が処理時間です。
ただし、 res.send() コードはさまざまな js ファイルに分散されているため、すべての URL 処理関数を変更することはできません。
正しい考え方は、ミドルウェアを使用してそれを実現することです。しかし、Nodejs には res.send() をインターセプトするメソッドがありません。これを破るにはどうすればよいでしょうか?
実際、考え方を少し変え、従来の OOP メソッドを放棄し、 res.send() を関数オブジェクトとして見る限り、最初に元の処理関数 res.send を保存し、次に res.send を関数で置き換えることができます。独自の処理関数:
app.use (function (req, res, next) { // 記録開始時刻: var exec_start_at = Date.now(); //元の処理関数を保存します。 var _send = res.send; // 独自のハンドラー関数をバインドします。 res.send = 関数() { // ヘッダーを送信: res.set('X 実行時間', String(Date.now() - exec_start_at)); // 元の処理関数を呼び出します。 return _send.apply(res, 引数); }; 次(); });
わずか数行のコードで、タイムスタンプが作成されます。
res.render() は内部で res.send() を呼び出すため、 res.render() メソッドを処理する必要はありません。
apply() 関数を呼び出すときは、 res オブジェクトを渡すことが重要です。そうしないと、元の処理関数の this が未定義を指し、エラーが直接発生します。
測定されたホームページ応答時間 9 ミリ秒
用語集:
QPS: 1 秒あたりのクエリ数は、サーバーが応答できるクエリの数を意味します。 per Second は、特定のクエリ サーバーが指定された期間内に処理するトラフィックの量の尺度です。
インターネットでは、ドメイン ネーム システム サーバーとして機能するマシンのパフォーマンスは、1 秒あたりのクエリ数によって測定されることがよくあります。
TPS: TransactionsPerSecond の略で、1 秒あたりのトランザクション数です。ソフトウェアのテスト結果の測定単位です。トランザクションとは、クライアントがサーバーにリクエストを送信し、サーバーが応答するプロセスを指します。クライアントは、リクエストを送信したときに計測を開始し、サーバーの応答を受信したときに終了して、使用時間と完了したトランザクションの数を計算します。
QPS と TPS: QPS は基本的に TPS に似ていますが、違いは、ページへの訪問が TPS を形成することですが、ページ リクエストはサーバーに対して複数のリクエストを生成する可能性があり、サーバーはこれらのリクエストを「QPS」としてカウントできることです。たとえば、ページにアクセスするとサーバーに 2 回リクエストが発生し、1 回のアクセスで「T」と 2 つの「Q」が生成されます。
応答時間: 応答データを受信するときの最初から最後までリクエストを実行するのにかかる合計時間、つまり、クライアントがリクエストを開始してからサーバーの応答結果を受信するまでの時間。
応答時間 RT (応答時間) は、システムの最も重要な指標の 1 つであり、その数値はシステムの速度を直接反映します。
実行数は、システムが同時に処理できるリクエストの数を指します。これは、システムの負荷容量も反映します。
システムのスループット (耐圧能力) は、リクエスト、外部インターフェイス、IO などの CPU 消費量と密接に関係しています。 1 つのリクエストの CPU 消費量が増えると、外部システム インターフェイスと IO 速度が遅くなり、システムのスループット能力が低下します。逆も同様です。
システム スループットのいくつかの重要なパラメータ: QPS (TPS)、同時実行数、および応答時間。
QPS (TPS): (Query Per Second) 1 秒あたりのリクエスト/トランザクションの数
Concurrency: システムが同時に処理するリクエスト/トランザクションの数
応答時間: 通常、平均応答時間は
上記の意味を理解した上で計算されます。それらの関係:
例を通して上記の概念を理解しましょう。 80/20 ルールによると、毎日の訪問者数の 80% が 20% の時間に集中している場合、この 20% の時間はピーク時間と呼ばれます。
1、 1 台のマシン上で 1 日あたり 300 ワットの PV が実行されます。このマシンにはどのくらいの QPS が必要ですか?
(3000000 * 0.8) / (86400 * 0.2) = 139 (QPS)
2. マシンの QPS が 58 の場合、それをサポートするには何台のマシンが必要ですか?
139 /58 = 3
この時点で、一般的な中小プロジェクトのフロントエンドアーキテクチャを行い、独自のノードサービスを展開する場合、PPTを報告するためにクラスターを形成するために必要なマシンの数がわかります。 PV で大まかな値を計算できます。
ストレステストを理解する必要があります(QPSを
取得するには、
ストレステストに依存する必要があります)
。パラメータは次のとおりです。
-n リクエストの合計 リクエストの数 -c concurrency 同時実行の数 -t timelimit テストの最大秒数(リクエストのタイムアウト時間と見なすことができます) -p postfile POST が必要なデータを含むファイル-T content-type POSTデータで使用するコンテンツタイプのヘッダ情報 コピーコード