溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何獲取Node性能監(jiān)控指標(biāo)

發(fā)布時(shí)間:2022-04-20 10:43:28 來源:億速云 閱讀:156 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“如何獲取Node性能監(jiān)控指標(biāo)”,在日常操作中,相信很多人在如何獲取Node性能監(jiān)控指標(biāo)問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何獲取Node性能監(jiān)控指標(biāo)”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

如何獲取Node性能監(jiān)控指標(biāo)

服務(wù)器的性能瓶頸通常為以下幾個(gè):

  • CPU 使用率

  • CPU 負(fù)載(load)

  • 內(nèi)存

  • 磁盤

  • I/O

  • 吞吐量 (Throughput)

  • 每秒查詢率 QPS(Query Per Second)

  • 日志監(jiān)控/真實(shí)QPS

  • 響應(yīng)時(shí)間

  • 進(jìn)程監(jiān)控

獲取 CPU 指標(biāo)

CPU 使用率與CPU 負(fù)載,這兩個(gè)從一定程度上都可以反映一臺(tái)機(jī)器的繁忙程度。

CPU 使用率

CPU 使用率是運(yùn)行的程序占用的 CPU 資源,表示機(jī)器在某個(gè)時(shí)間點(diǎn)的運(yùn)行程序的情況。使用率越高,說明機(jī)器在這個(gè)時(shí)間上運(yùn)行了很多程序,反之較少。使用率的高低與 CPU 強(qiáng)弱有直接關(guān)系。我們先了解一下相關(guān)的API和一些名詞解釋,幫助我們理解獲取CPU使用率的代碼。

os.cpus()

返回包含有關(guān)每個(gè)邏輯 CPU 內(nèi)核的信息的對(duì)象數(shù)組。

  • model: 一個(gè)字符串,指定CPU內(nèi)核的型號(hào)。

  • speed: 一個(gè)數(shù)字,指定CPU內(nèi)核的速度(以MHz為單位)。

  • times: 包含以下屬性的對(duì)象:

    • user  CPU 在用戶模式下花費(fèi)的毫秒數(shù)。

    • nice  CPU 在良好模式下花費(fèi)的毫秒數(shù)。

    • sys  CPU 在系統(tǒng)模式下花費(fèi)的毫秒數(shù)。

    • idle  CPU 在空閑模式下花費(fèi)的毫秒數(shù)。

    • irq  CPU 在中斷請(qǐng)求模式下花費(fèi)的毫秒數(shù)。

注意:nice值僅用于POSIX。在Windows操作系統(tǒng)上,nice所有處理器的值始終為0。

大家看到user,nice字段,有些同學(xué)就優(yōu)點(diǎn)懵逼了,我也是,所以仔細(xì)查詢了一下其意義,請(qǐng)接著。

user

user 表示 CPU 運(yùn)行在 用戶態(tài) 的時(shí)間占比。

應(yīng)用進(jìn)程執(zhí)行分為 用戶態(tài) 以及 內(nèi)核態(tài) : CPU 在用戶態(tài)執(zhí)行應(yīng)用進(jìn)程自身的代碼邏輯,通常是一些 邏輯數(shù)值計(jì)算 ; CPU 在內(nèi)核態(tài)執(zhí)行進(jìn)程發(fā)起的 系統(tǒng)調(diào)用 ,通常是響應(yīng)進(jìn)程對(duì)資源的請(qǐng)求。

用戶空間程序是任何不屬于內(nèi)核的進(jìn)程。 Shell、編譯器、數(shù)據(jù)庫(kù)、Web 服務(wù)器以及與桌面相關(guān)的程序都是用戶空間進(jìn)程。 如果處理器沒有空閑,那么大部分 CPU 時(shí)間應(yīng)該花在運(yùn)行用戶空間進(jìn)程上是很正常的。

nice

nice 表示 CPU 運(yùn)行在 低優(yōu)先級(jí)用戶態(tài) 的時(shí)間占比,低優(yōu)先級(jí)意味著進(jìn)程 nice 值小于 0 。

system

user 表示 CPU 運(yùn)行在 內(nèi)核態(tài) 的時(shí)間占比。

一般而言, 內(nèi)核態(tài) CPU 使用率不應(yīng)過高,除非應(yīng)用進(jìn)程發(fā)起大量系統(tǒng)調(diào)用。如果太高,表示系統(tǒng)調(diào)用時(shí)間長(zhǎng),例如是IO操作頻繁。

idle

idle 表示 CPU 在空閑狀態(tài)的時(shí)間占比,該狀態(tài)下 CPU 沒有任何任務(wù)可執(zhí)行。

irq

irq 表示 CPU 處理 硬件中斷 的時(shí)間占比。

網(wǎng)卡中斷 是一個(gè)典型的例子:網(wǎng)卡接到數(shù)據(jù)包后,通過硬件中斷通知 CPU 進(jìn)行處理。 如果系統(tǒng)網(wǎng)絡(luò)流量非常大,則可觀察到 irq 使用率明顯升高。

結(jié)論:

用戶態(tài)小于70%,內(nèi)核態(tài)小于35%且整體小于70%,可以算作健康狀態(tài)。

以下示例說明了Node.js中os.cpus()方法的使用:

范例1:

// Node.js program to demonstrate the    
// os.cpus() method 
  
// Allocating os module 
const os = require('os'); 
  
// Printing os.cpus() values 
console.log(os.cpus());

輸出:

[ { model:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz',
    speed:2712,
    times:
     { user:900000, nice:0, sys:940265, idle:11928546, irq:147046 } },
  { model:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz',
    speed:2712,
    times:
     { user:860875, nice:0, sys:507093, idle:12400500, irq:27062 } },
  { model:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz',
    speed:2712,
    times:
     { user:1273421, nice:0, sys:618765, idle:11876281, irq:13125 } },
  { model:'Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz',
    speed:2712,
    times:
     { user:943921, nice:0, sys:460109, idle:12364453, irq:12437 } } ]

下面是如何獲取cpu利用率的代碼

const os = require('os');
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

class OSUtils {
  constructor() {
    this.cpuUsageMSDefault = 1000; // CPU 利用率默認(rèn)時(shí)間段
  }

  /**
   * 獲取某時(shí)間段 CPU 利用率
   * @param { Number } Options.ms [時(shí)間段,默認(rèn)是 1000ms,即 1 秒鐘]
   * @param { Boolean } Options.percentage [true(以百分比結(jié)果返回)|false] 
   * @returns { Promise }
   */
  async getCPUUsage(options={}) {
    const that = this;
    let { cpuUsageMS, percentage } = options;
    cpuUsageMS = cpuUsageMS || that.cpuUsageMSDefault;
    const t1 = that._getCPUInfo(); // t1 時(shí)間點(diǎn) CPU 信息

    await sleep(cpuUsageMS);

    const t2 = that._getCPUInfo(); // t2 時(shí)間點(diǎn) CPU 信息
    const idle = t2.idle - t1.idle;
    const total = t2.total - t1.total;
    let usage = 1 - idle / total;

    if (percentage) usage = (usage * 100.0).toFixed(2) + "%";

    return usage;
  }

  /**
   * 獲取 CPU 瞬時(shí)時(shí)間信息
   * @returns { Object } CPU 信息
   * user <number> CPU 在用戶模式下花費(fèi)的毫秒數(shù)。
   * nice <number> CPU 在良好模式下花費(fèi)的毫秒數(shù)。
   * sys <number> CPU 在系統(tǒng)模式下花費(fèi)的毫秒數(shù)。
   * idle <number> CPU 在空閑模式下花費(fèi)的毫秒數(shù)。
   * irq <number> CPU 在中斷請(qǐng)求模式下花費(fèi)的毫秒數(shù)。
   */
  _getCPUInfo() {
    const cpus = os.cpus();
    let user = 0, nice = 0, sys = 0, idle = 0, irq = 0, total = 0;

    for (let cpu in cpus) {
      const times = cpus[cpu].times;
      user += times.user;
      nice += times.nice;
      sys += times.sys;
      idle += times.idle;
      irq += times.irq;
    }

    total += user + nice + sys + idle + irq;

    return {
      user,
      sys,
      idle,
      total,
    }
  }
}

const cpuUsage = new OSUtils().getCPUUsage({ percentage: true });
console.log('cpuUsage: ', cpuUsage.then(data=>console.log(data)));  // 我的電腦是6.15%

CPU 負(fù)載

CPU的負(fù)載(loadavg)很好理解,指某段時(shí)間內(nèi)占用 CPU 時(shí)間的進(jìn)程和等待 CPU 時(shí)間的進(jìn)程數(shù)為平均負(fù)載(load average),這里等待CPU 時(shí)間的進(jìn)程是指等待被喚醒的進(jìn)程,不包括處于wait狀態(tài)進(jìn)程。

在此之前我們需要學(xué)習(xí)一個(gè)node的API

os.loadavg()

返回包含 1、5 和 15 分鐘平均負(fù)載的數(shù)組。

平均負(fù)載是操作系統(tǒng)計(jì)算的系統(tǒng)活動(dòng)量度,并表示為小數(shù)。

平均負(fù)載是 Unix 特有的概念。 在 Windows 上,返回值始終為 [0, 0, 0]

它用來描述操作系統(tǒng)當(dāng)前的繁忙程度,可以簡(jiǎn)單地理解為CPU在單位時(shí)間內(nèi)正在使用和等待使用CPU的平均任務(wù)數(shù)。CPU load過高,說明進(jìn)程數(shù)量過多,在Node中可能體現(xiàn)在用紫禁城模塊反復(fù)啟動(dòng)新的進(jìn)程。

const os = require('os');
// CPU線程數(shù)
const length = os.cpus().length;
// 單核CPU的平均負(fù)載,返回一個(gè)包含 1、5、15 分鐘平均負(fù)載的數(shù)組
os.loadavg().map(load => load / length);

內(nèi)存指標(biāo)

我們先解釋一個(gè)API,要么你看不懂我們獲取內(nèi)存指標(biāo)的代碼

process.memoryUsage():

該函數(shù)返回4個(gè)參數(shù),含義及差別如下:

  • rss: (Resident Set Size)操作系統(tǒng)分配給進(jìn)程的總的內(nèi)存大小。包括所有 C++ 和 JavaScript 對(duì)象和代碼。(比如,堆棧和代碼段)

  • heapTotal:堆的總大小,包括3個(gè)部分,

    • 已分配的內(nèi)存,用于對(duì)象的創(chuàng)建和存儲(chǔ),對(duì)應(yīng)于heapUsed

    • 未分配的但可用于分配的內(nèi)存

    • 未分配的但不能分配的內(nèi)存,例如在垃圾收集(GC)之前對(duì)象之間的內(nèi)存碎片

  • heapUsed: 已分配的內(nèi)存,即堆中所有對(duì)象的總大小,是heapTotal的子集。

  • external: 進(jìn)程使用到的系統(tǒng)鏈接庫(kù)所占用的內(nèi)存, 比如buffer就是屬于external里的數(shù)據(jù)。buffer數(shù)據(jù)不同于其他對(duì)象,它不經(jīng)過V8的內(nèi)存分配機(jī)制,所以也不會(huì)有堆內(nèi)存大小限制。

用如下代碼,打印一個(gè)子進(jìn)程的內(nèi)存使用情況,可以看出rss大致等于top命令的RES。另外,主進(jìn)程的內(nèi)存只有33M比子進(jìn)程的內(nèi)存還小,可見它們的內(nèi)存占用情況是獨(dú)立統(tǒng)計(jì)的。

var showMem = function(){
   var mem = process.memoryUsage();
   var format = function(bytes){
       return (bytes / 1024 / 1024).toFixed(2) + ' MB';
   };
   console.log('Process: heapTotal ' + format(mem.heapTotal) + ' heapUsed ' + format(mem.heapUsed) + ' rss ' + format(mem.rss) + ' external:' + format(mem.external));
   console.log('-----------------------------------------------------------');
};

對(duì)于Node而言,一旦出現(xiàn)內(nèi)存泄漏,不是那么容易排查。如果監(jiān)控到內(nèi)存只升不降,那么鐵定存在內(nèi)存泄露問題。健康的內(nèi)存使用應(yīng)該有升有降。訪問大的時(shí)候上升,訪問回落下降

獲取內(nèi)存指標(biāo)的代碼

const os = require('os');
// 查看當(dāng)前 Node 進(jìn)程內(nèi)存使用情況
const { rss, heapUsed, heapTotal } = process.memoryUsage();
// 獲取系統(tǒng)空閑內(nèi)存
const systemFree = os.freemem();
// 獲取系統(tǒng)總內(nèi)存
const systemTotal = os.totalmem();

module.exports = {
  memory: () => {
    return {
      system: 1 - systemFree / systemTotal,  // 系統(tǒng)內(nèi)存占用率
      heap: heapUsed / headTotal,   // 當(dāng)前 Node 進(jìn)程內(nèi)存占用率
      node: rss / systemTotal,         // 當(dāng)前 Node 進(jìn)程內(nèi)存占用系統(tǒng)內(nèi)存的比例
    }
  }
}

磁盤空間指標(biāo)

磁盤監(jiān)控主要是監(jiān)控磁盤的用量。由于日志頻繁寫的緣故,磁盤空間被漸漸用光。一旦磁盤不夠用,將會(huì)引發(fā)系統(tǒng)的各種問題。給磁盤的使用量設(shè)置一個(gè)上限,一旦磁盤用量超過警戒值,服務(wù)器的管理者就應(yīng)該整理日志或者清理磁盤。

以下代碼參考easy monitor3.0

  • 先用df -P獲得所有磁盤情況,這個(gè)-P是為了防止有換行

  • startsWith('/')保證是真實(shí)磁盤,不是虛擬的

  • line.match(/(\d+)%\s+(/.*$)/) => 匹配磁盤情況和掛載的磁盤,比如'1%    /System/Volumes/Preboot'

  • match[1]是字符串,表示使用率, match[2]表示掛載的磁盤名稱

const { execSync } = require('child_process');
const result = execSync('df -P', { encoding: 'utf8'})
const lines = result.split('\n');
const metric = {};
lines.forEach(line => {
  if (line.startsWith('/')) {
    const match = line.match(/(\d+)%\s+(\/.*$)/);
    if (match) {
      const rate = parseInt(match[1] || 0);
      const mounted = match[2];
      if (!mounted.startsWith('/Volumes/') && !mounted.startsWith('/private/')) {
        metric[mounted] = rate;
      }
    }
  }
});
console.log(metric)

I/O指標(biāo)

I/O負(fù)載指的主要是磁盤I/O。反應(yīng)的是磁盤上的讀寫情況,對(duì)于Node編寫的應(yīng)用,主要是面向網(wǎng)絡(luò)服務(wù),是不太可能出現(xiàn)I/O負(fù)載過高的情況,多讀書的I/O的壓力來源于數(shù)據(jù)庫(kù)。

獲取I/O指標(biāo),我們要了解一個(gè)linux命令,叫iostat,如果沒有安裝,需要安裝一下,我們看一下這個(gè)命令為啥能反應(yīng)I/O指標(biāo)

iostat -dx

如何獲取Node性能監(jiān)控指標(biāo)

屬性說明

rrqm/s: 每秒進(jìn)行 merge 的讀操作數(shù)目。即 rmerge/s(每秒對(duì)該設(shè)備的讀請(qǐng)求被合并次數(shù),文件系統(tǒng)會(huì)對(duì)讀取同塊(block)的請(qǐng)求進(jìn)行合并)
wrqm/s: 每秒進(jìn)行 merge 的寫操作數(shù)目。即 wmerge/s(每秒對(duì)該設(shè)備的寫請(qǐng)求被合并次數(shù))
r/s: 每秒完成的讀 I/O 設(shè)備次數(shù)。即 rio/s
w/s: 每秒完成的寫 I/O 設(shè)備次數(shù)。即 wio/s
rsec/s: 每秒讀扇區(qū)數(shù)。即 rsect/s
wsec/s: 每秒寫扇區(qū)數(shù)。即 wsect/s
rkB/s: 每秒讀K字節(jié)數(shù)。是 rsect/s 的一半,因?yàn)槊可葏^(qū)大小為512字節(jié)。
wkB/s: 每秒寫K字節(jié)數(shù)。是 wsect/s 的一半。
avgrq-sz: 平均每次設(shè)備I/O操作的數(shù)據(jù)大小 (扇區(qū))。
avgqu-sz: 平均I/O隊(duì)列長(zhǎng)度。
await: 平均每次設(shè)備I/O操作的等待時(shí)間 (毫秒)。
svctm: 平均每次設(shè)備I/O操作的處理時(shí)間 (毫秒)。
%util: 一秒中有百分之多少的時(shí)間用于 I/O 操作,即被io消耗的cpu百分比

我們只監(jiān)控%util就行

  • 如果 %util 接近 100% ,說明產(chǎn)生的I/O請(qǐng)求太多,I/O系統(tǒng)已經(jīng)滿負(fù)荷,該磁盤可能存在瓶頸。

  • 如果 await 遠(yuǎn)大于 svctm,說明 I/O 隊(duì)列太長(zhǎng),應(yīng)用得到的響應(yīng)時(shí)間變慢,如果響應(yīng)時(shí)間超過了用戶可以容許的范圍,這時(shí)可以考慮更換更快的磁盤,調(diào)整內(nèi)核 elevator 算法,優(yōu)化應(yīng)用,或者升級(jí) CPU。

響應(yīng)時(shí)間RT監(jiān)控

監(jiān)控Nodejs的頁面響應(yīng)時(shí)間, 方案選自廖雪峰老師的博客文章。

最近想監(jiān)控一下Nodejs的性能。記錄分析Log太麻煩,最簡(jiǎn)單的方式是記錄每個(gè)HTTP請(qǐng)求的處理時(shí)間,直接在HTTP Response Header中返回。

記錄HTTP請(qǐng)求的時(shí)間很簡(jiǎn)單,就是收到請(qǐng)求記一個(gè)時(shí)間戳,響應(yīng)請(qǐng)求的時(shí)候再記一個(gè)時(shí)間戳,兩個(gè)時(shí)間戳之差就是處理時(shí)間。

但是,res.send()代碼遍布各個(gè)js文件,總不能把每個(gè)URL處理函數(shù)都改一遍吧。

正確的思路是用middleware實(shí)現(xiàn)。但是Nodejs沒有任何攔截res.send()的方法,怎么破?

其實(shí)只要稍微轉(zhuǎn)換一下思路,放棄傳統(tǒng)的OOP方式,以函數(shù)對(duì)象看待res.send(),我們就可以先保存原始的處理函數(shù)res.send,再用自己的處理函數(shù)替換res.send:

app.use(function (req, res, next) {
    // 記錄start time:
    var exec_start_at = Date.now();
    // 保存原始處理函數(shù):
    var _send = res.send;
    // 綁定我們自己的處理函數(shù):
    res.send = function () {
        // 發(fā)送Header:
        res.set('X-Execution-Time', String(Date.now() - exec_start_at));
        // 調(diào)用原始處理函數(shù):
        return _send.apply(res, arguments);
    };
    next();
});

只用了幾行代碼,就把時(shí)間戳搞定了。

對(duì)于res.render()方法不需要處理,因?yàn)閞es.render()內(nèi)部調(diào)用了res.send()。

調(diào)用apply()函數(shù)時(shí),傳入res對(duì)象很重要,否則原始的處理函數(shù)的this指向undefined直接導(dǎo)致出錯(cuò)。

實(shí)測(cè)首頁響應(yīng)時(shí)間9毫秒

監(jiān)控吞吐量/每秒查詢率 QPS

名詞解釋:

一、QPS,每秒查詢

QPS:Queries Per Second意思是“每秒查詢率”,是一臺(tái)服務(wù)器每秒能夠響應(yīng)的查詢次數(shù),是對(duì)一個(gè)特定的查詢服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)。

互聯(lián)網(wǎng)中,作為域名系統(tǒng)服務(wù)器的機(jī)器的性能經(jīng)常用每秒查詢率來衡量。

二、TPS,每秒事務(wù)

TPS:是TransactionsPerSecond的縮寫,也就是事務(wù)數(shù)/秒。它是軟件測(cè)試結(jié)果的測(cè)量單位。一個(gè)事務(wù)是指一個(gè)客戶機(jī)向服務(wù)器發(fā)送請(qǐng)求然后服務(wù)器做出反應(yīng)的過程??蛻魴C(jī)在發(fā)送請(qǐng)求時(shí)開始計(jì)時(shí),收到服務(wù)器響應(yīng)后結(jié)束計(jì)時(shí),以此來計(jì)算使用的時(shí)間和完成的事務(wù)個(gè)數(shù)。

QPS vs TPS:QPS基本類似于TPS,但是不同的是,對(duì)于一個(gè)頁面的一次訪問,形成一個(gè)TPS;但一次頁面請(qǐng)求,可能產(chǎn)生多次對(duì)服務(wù)器的請(qǐng)求,服務(wù)器對(duì)這些請(qǐng)求,就可計(jì)入“QPS”之中。如,訪問一個(gè)頁面會(huì)請(qǐng)求服務(wù)器2次,一次訪問,產(chǎn)生一個(gè)“T”,產(chǎn)生2個(gè)“Q”。

三、RT,響應(yīng)時(shí)間

響應(yīng)時(shí)間:執(zhí)行一個(gè)請(qǐng)求從開始到最后收到響應(yīng)數(shù)據(jù)所花費(fèi)的總體時(shí)間,即從客戶端發(fā)起請(qǐng)求到收到服務(wù)器響應(yīng)結(jié)果的時(shí)間。

響應(yīng)時(shí)間RT(Response-time),是一個(gè)系統(tǒng)最重要的指標(biāo)之一,它的數(shù)值大小直接反應(yīng)了系統(tǒng)的快慢。

四、并發(fā)數(shù)

并發(fā)數(shù)是指系統(tǒng)同時(shí)能處理的請(qǐng)求數(shù)量,這個(gè)也是反應(yīng)了系統(tǒng)的負(fù)載能力。

五、吞吐量

系統(tǒng)的吞吐量(承壓能力)與request對(duì)CPU的消耗、外部接口、IO等等緊密關(guān)聯(lián)。單個(gè)request 對(duì)CPU消耗越高,外部系統(tǒng)接口、IO速度越慢,系統(tǒng)吞吐能力越低,反之越高。

系統(tǒng)吞吐量幾個(gè)重要參數(shù):QPS(TPS)、并發(fā)數(shù)、響應(yīng)時(shí)間。

  • QPS(TPS):(Query Per Second)每秒鐘request/事務(wù) 數(shù)量

  • 并發(fā)數(shù): 系統(tǒng)同時(shí)處理的request/事務(wù)數(shù)

  • 響應(yīng)時(shí)間: 一般取平均響應(yīng)時(shí)間

理解了上面三個(gè)要素的意義之后,就能推算出它們之間的關(guān)系:

  • QPS(TPS)= 并發(fā)數(shù)/平均響應(yīng)時(shí)間

  • 并發(fā)數(shù) = QPS*平均響應(yīng)時(shí)間

六、實(shí)際舉例

我們通過一個(gè)實(shí)例來把上面幾個(gè)概念串起來理解。按二八定律來看,如果每天 80% 的訪問集中在 20% 的時(shí)間里,這 20% 時(shí)間就叫做峰值時(shí)間。

  • 公式:( 總PV數(shù) * 80% ) / ( 每天秒數(shù) * 20% ) = 峰值時(shí)間每秒請(qǐng)求數(shù)(QPS)

  • 機(jī)器:峰值時(shí)間每秒QPS / 單臺(tái)機(jī)器的QPS = 需要的機(jī)器

1、每天300w PV 的在單臺(tái)機(jī)器上,這臺(tái)機(jī)器需要多少Q(mào)PS?
( 3000000 * 0.8 ) / (86400 * 0.2 ) = 139 (QPS)

2、如果一臺(tái)機(jī)器的QPS是58,需要幾臺(tái)機(jī)器來支持?
139 / 58 = 3

到這里,以后如果你做一般中小項(xiàng)目的前端架構(gòu),在部署自己的node服務(wù),就知道需要多少機(jī)器組成集群來匯報(bào)ppt了吧,哈哈,有pv就能推算一個(gè)初略值。

我們需要了解一下壓力測(cè)試(我們要靠壓測(cè)獲取qps),以ab命令為例:

命令格式:

ab [options] [http://]hostname[:port]/path

常用參數(shù)如下:

-n requests 總請(qǐng)求數(shù)
-c concurrency 并發(fā)數(shù)
-t timelimit 測(cè)試所進(jìn)行的最大秒數(shù), 可以當(dāng)做請(qǐng)求的超時(shí)時(shí)間
-p postfile 包含了需要POST的數(shù)據(jù)的文件
-T content-type POST數(shù)據(jù)所使用的Content-type頭信息復(fù)制代碼

更多參數(shù)請(qǐng)查看官方文檔。

http://httpd.apache.org/docs/2.2/programs/ab.html

例如測(cè)試某個(gè)GET請(qǐng)求接口:

ab -n 10000 -c 100 -t 10 "http://127.0.0.1:8080/api/v1/posts?size=10"

得到一下數(shù)據(jù):

如何獲取Node性能監(jiān)控指標(biāo)

我們從中獲取幾個(gè)關(guān)鍵指標(biāo):

  • 吞吐率(Requests per second)在圖上有顯示

服務(wù)器并發(fā)處理能力的量化描述,單位是reqs/s,指的是在某個(gè)并發(fā)用戶數(shù)下單位時(shí)間內(nèi)處理的請(qǐng)求數(shù)。某個(gè)并發(fā)用戶數(shù)下單位時(shí)間內(nèi)能處理的最大請(qǐng)求數(shù),稱之為最大吞吐率。

記住:吞吐率是基于并發(fā)用戶數(shù)的。這句話代表了兩個(gè)含義:

  • a、吞吐率和并發(fā)用戶數(shù)相關(guān)

  • b、不同的并發(fā)用戶數(shù)下,吞吐率一般是不同的

計(jì)算公式:

總請(qǐng)求數(shù)/處理完成這些請(qǐng)求數(shù)所花費(fèi)的時(shí)間

必須要說明的是,這個(gè)數(shù)值表示當(dāng)前機(jī)器的整體性能,值越大越好。

2、QPS每秒查詢率(Query Per Second)

  每秒查詢率QPS是對(duì)一個(gè)特定的查詢服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn),在因特網(wǎng)上,作為域名系統(tǒng)服務(wù)器的機(jī)器的性能經(jīng)常用每秒查詢率來衡量,即每秒的響應(yīng)請(qǐng)求數(shù),也即是最大吞吐能力。

計(jì)算公式

QPS(TPS)= 并發(fā)數(shù)/平均響應(yīng)時(shí)間(Time per request)

在上圖里有Time per request的值,然后我們也有并發(fā)數(shù)數(shù)據(jù),就可以計(jì)算出QPS。

這個(gè)QPS是壓測(cè)數(shù)據(jù),真實(shí)的qps,可使用日志監(jiān)控來獲取。

日志監(jiān)控

通常情況下,隨著系統(tǒng)的運(yùn)行,我們的后臺(tái)服務(wù)會(huì)產(chǎn)生各種日志,應(yīng)用程序會(huì)產(chǎn)生應(yīng)用程序的訪問日志、錯(cuò)誤日志,運(yùn)行日志,網(wǎng)絡(luò)日志,我們需要一個(gè)展示平臺(tái)去展示這些日志。

后端一般都用比如ELk去展示,我們前端都是ui老手了,自己可以畫定制的UI界面,不多說了,主要是日志本身要打印符合一定的規(guī)范,這樣格式化的數(shù)據(jù)更利于分析和展示。

并且業(yè)務(wù)邏輯型的監(jiān)控主要體現(xiàn)在日志上。通過監(jiān)控異常日志文件的變動(dòng),將新增的異常按異常類型和數(shù)量反映出來。某些異常與具體的某個(gè)子系統(tǒng)相關(guān),監(jiān)控出現(xiàn)的某個(gè)異常也能反映出子系統(tǒng)的狀態(tài)。

在體制監(jiān)控里也能體現(xiàn)出實(shí)際業(yè)務(wù)的QPS值。觀察QPS的表現(xiàn)能夠檢查業(yè)務(wù)在時(shí)間上的分部。

此外,從訪問日志中也能實(shí)現(xiàn)PV和UV的監(jiān)控。并且可以從中分析出使用者的習(xí)慣,預(yù)知訪問高峰。

響應(yīng)時(shí)間

這個(gè)也可以通過訪問日志來獲取,并且真實(shí)響應(yīng)時(shí)間是需要在controller上打log的。

進(jìn)程監(jiān)控

監(jiān)控進(jìn)程一般是檢查操作系統(tǒng)中運(yùn)行的應(yīng)用進(jìn)程數(shù),比如對(duì)于采用多進(jìn)程架構(gòu)的node應(yīng)用,就需要檢查工作進(jìn)程的數(shù)量,如果低于預(yù)期值,就當(dāng)發(fā)出報(bào)警。

查看進(jìn)程數(shù)在linux下很簡(jiǎn)單,

假如我們通過Node 提供 child_process 模塊來實(shí)現(xiàn)多核 CPU 的利用。child_process.fork() 函數(shù)來實(shí)現(xiàn)進(jìn)程的復(fù)制。

worker.js 代碼如下:

var http = require('http')\
http.createServer(function(req, res) {\
res.writeHead(200, { 'Content-Type': 'text/plain' })\
res.end('Hello World\n')\
}).listen(Math.round((1 + Math.random()) * 1000), '127.0.0.1')\

通過 node worker.js 啟動(dòng)它,會(huì)監(jiān)聽 1000 到 2000 之間的一個(gè)隨機(jī)端口。

master.js 代碼如下:

var fork = require('child_process').fork
var cpus = require('os').cpus()
for (var i = 0; i < cpus.length; i++) {
  fork('./worker.js')
}

查看進(jìn)程數(shù)的 命令如下:

ps aux | grep worker.js
$ ps aux | grep worker.js
lizhen 1475 0.0 0.0 2432768 600 s003 S+ 3:27AM 0:00.00 grep worker.js\
lizhen 1440 0.0 0.2 3022452 12680 s003 S 3:25AM 0:00.14 /usr/local/bin/node ./worker.js\
lizhen 1439 0.0 0.2 3023476 12716 s003 S 3:25AM 0:00.14 /usr/local/bin/node ./worker.js\
lizhen 1438 0.0 0.2 3022452 12704 s003 S 3:25AM 0:00.14 /usr/local/bin/node ./worker.js\
lizhen 1437 0.0 0.2 3031668 12696 s003 S 3:25AM 0:00.15 /usr/local/bin/node ./worker.js\

到此,關(guān)于“如何獲取Node性能監(jiān)控指標(biāo)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI