這篇文章主要介紹“如何獲取Node性能監(jiān)控指標(biāo)”,在日常操作中,相信很多人在如何獲取Node性能監(jiān)控指標(biāo)問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何獲取Node性能監(jiān)控指標(biāo)”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、做網(wǎng)站、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、廣信ssl等。為超過(guò)千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢(xún)和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的廣信網(wǎng)站制作公司
服務(wù)器的性能瓶頸通常為以下幾個(gè):
CPU 使用率
CPU 負(fù)載(load)
內(nèi)存
磁盤(pán)
I/O
吞吐量 (Throughput)
每秒查詢(xún)率 QPS(Query Per Second)
日志監(jiān)控/真實(shí)QPS
響應(yīng)時(shí)間
進(jìn)程監(jiān)控
CPU 使用率與CPU 負(fù)載,這兩個(gè)從一定程度上都可以反映一臺(tái)機(jī)器的繁忙程度。
CPU 使用率是運(yùn)行的程序占用的 CPU 資源,表示機(jī)器在某個(gè)時(shí)間點(diǎn)的運(yùn)行程序的情況。使用率越高,說(shuō)明機(jī)器在這個(gè)時(shí)間上運(yùn)行了很多程序,反之較少。使用率的高低與 CPU 強(qiáng)弱有直接關(guān)系。我們先了解一下相關(guān)的API和一些名詞解釋?zhuān)瑤椭覀兝斫猥@取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 在用戶(hù)模式下花費(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ì)查詢(xún)了一下其意義,請(qǐng)接著。
user 表示 CPU 運(yùn)行在 用戶(hù)態(tài)的時(shí)間占比。
應(yīng)用進(jìn)程執(zhí)行分為 用戶(hù)態(tài)以及 內(nèi)核態(tài): CPU 在用戶(hù)態(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)求。
用戶(hù)空間程序是任何不屬于內(nèi)核的進(jìn)程。 Shell、編譯器、數(shù)據(jù)庫(kù)、Web 服務(wù)器以及與桌面相關(guān)的程序都是用戶(hù)空間進(jìn)程。 如果處理器沒(méi)有空閑,那么大部分 CPU 時(shí)間應(yīng)該花在運(yùn)行用戶(hù)空間進(jìn)程上是很正常的。
nice 表示 CPU 運(yùn)行在 低優(yōu)先級(jí)用戶(hù)態(tài)的時(shí)間占比,低優(yōu)先級(jí)意味著進(jìn)程 nice 值小于 0 。
user 表示 CPU 運(yùn)行在 內(nèi)核態(tài)的時(shí)間占比。
一般而言, 內(nèi)核態(tài)CPU 使用率不應(yīng)過(guò)高,除非應(yīng)用進(jìn)程發(fā)起大量系統(tǒng)調(diào)用。如果太高,表示系統(tǒng)調(diào)用時(shí)間長(zhǎng),例如是IO操作頻繁。
idle 表示 CPU 在空閑狀態(tài)的時(shí)間占比,該狀態(tài)下 CPU 沒(méi)有任何任務(wù)可執(zhí)行。
irq 表示 CPU 處理 硬件中斷的時(shí)間占比。
網(wǎng)卡中斷是一個(gè)典型的例子:網(wǎng)卡接到數(shù)據(jù)包后,通過(guò)硬件中斷通知 CPU 進(jìn)行處理。 如果系統(tǒng)網(wǎng)絡(luò)流量非常大,則可觀(guān)察到 irq 使用率明顯升高。
用戶(hù)態(tài)小于70%,內(nèi)核態(tài)小于35%且整體小于70%,可以算作健康狀態(tài)。
以下示例說(shuō)明了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 信息 * userCPU 在用戶(hù)模式下花費(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ù)。 */ _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ù)載(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]
它用來(lái)描述操作系統(tǒng)當(dāng)前的繁忙程度,可以簡(jiǎn)單地理解為CPU在單位時(shí)間內(nèi)正在使用和等待使用CPU的平均任務(wù)數(shù)。CPU load過(guò)高,說(shuō)明進(jìn)程數(shù)量過(guò)多,在Node中可能體現(xiàn)在用紫禁城模塊反復(fù)啟動(dòng)新的進(jìn)程。
const os = require('os'); // CPU線(xiàn)程數(shù) const length = os.cpus().length; // 單核CPU的平均負(fù)載,返回一個(gè)包含 1、5、15 分鐘平均負(fù)載的數(shù)組 os.loadavg().map(load => load / length);
我們先解釋一個(gè)API,要么你看不懂我們獲取內(nèi)存指標(biāo)的代碼
該函數(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)過(guò)V8的內(nèi)存分配機(jī)制,所以也不會(huì)有堆內(nèi)存大小限制。
用如下代碼,打印一個(gè)子進(jìn)程的內(nèi)存使用情況,可以看出rss大致等于top命令的RES。另外,主進(jìn)程的內(nèi)存只有33M比子進(jìn)程的內(nèi)存還小,可見(jiàn)它們的內(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)存泄露問(wèn)題。健康的內(nèi)存使用應(yīng)該有升有降。訪(fǎng)問(wèn)大的時(shí)候上升,訪(fǎng)問(wèn)回落下降
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)存的比例 } } }
磁盤(pán)監(jiān)控主要是監(jiān)控磁盤(pán)的用量。由于日志頻繁寫(xiě)的緣故,磁盤(pán)空間被漸漸用光。一旦磁盤(pán)不夠用,將會(huì)引發(fā)系統(tǒng)的各種問(wèn)題。給磁盤(pán)的使用量設(shè)置一個(gè)上限,一旦磁盤(pán)用量超過(guò)警戒值,服務(wù)器的管理者就應(yīng)該整理日志或者清理磁盤(pán)。
以下代碼參考easy monitor3.0
先用df -P獲得所有磁盤(pán)情況,這個(gè)-P是為了防止有換行
startsWith('/')保證是真實(shí)磁盤(pán),不是虛擬的
line.match(/(\d+)%\s+(/.*$)/) => 匹配磁盤(pán)情況和掛載的磁盤(pán),比如'1% /System/Volumes/Preboot'
match[1]是字符串,表示使用率, match[2]表示掛載的磁盤(pán)名稱(chēng)
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負(fù)載指的主要是磁盤(pán)I/O。反應(yīng)的是磁盤(pán)上的讀寫(xiě)情況,對(duì)于Node編寫(xiě)的應(yīng)用,主要是面向網(wǎng)絡(luò)服務(wù),是不太可能出現(xiàn)I/O負(fù)載過(guò)高的情況,多讀書(shū)的I/O的壓力來(lái)源于數(shù)據(jù)庫(kù)。
獲取I/O指標(biāo),我們要了解一個(gè)linux命令,叫iostat,如果沒(méi)有安裝,需要安裝一下,我們看一下這個(gè)命令為啥能反應(yīng)I/O指標(biāo)
iostat -dx
屬性說(shuō)明
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 的寫(xiě)操作數(shù)目。即 wmerge/s(每秒對(duì)該設(shè)備的寫(xiě)請(qǐng)求被合并次數(shù)) r/s: 每秒完成的讀 I/O 設(shè)備次數(shù)。即 rio/s w/s: 每秒完成的寫(xiě) I/O 設(shè)備次數(shù)。即 wio/s rsec/s: 每秒讀扇區(qū)數(shù)。即 rsect/s wsec/s: 每秒寫(xiě)扇區(qū)數(shù)。即 wsect/s rkB/s: 每秒讀K字節(jié)數(shù)。是 rsect/s 的一半,因?yàn)槊可葏^(qū)大小為512字節(jié)。 wkB/s: 每秒寫(xiě)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%,說(shuō)明產(chǎn)生的I/O請(qǐng)求太多,I/O系統(tǒng)已經(jīng)滿(mǎn)負(fù)荷,該磁盤(pán)可能存在瓶頸。
如果 await 遠(yuǎn)大于 svctm,說(shuō)明 I/O 隊(duì)列太長(zhǎng),應(yīng)用得到的響應(yīng)時(shí)間變慢,如果響應(yīng)時(shí)間超過(guò)了用戶(hù)可以容許的范圍,這時(shí)可以考慮更換更快的磁盤(pán),調(diào)整內(nèi)核 elevator 算法,優(yōu)化應(yīng)用,或者升級(jí) CPU。
監(jiān)控Nodejs的頁(yè)面響應(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沒(méi)有任何攔截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è)響應(yīng)時(shí)間9毫秒
名詞解釋?zhuān)?/p>
QPS:Queries Per Second意思是“每秒查詢(xún)率”,是一臺(tái)服務(wù)器每秒能夠響應(yīng)的查詢(xún)次數(shù),是對(duì)一個(gè)特定的查詢(xún)服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)。
互聯(lián)網(wǎng)中,作為域名系統(tǒng)服務(wù)器的機(jī)器的性能經(jīng)常用每秒查詢(xún)率來(lái)衡量。
TPS:是TransactionsPerSecond的縮寫(xiě),也就是事務(wù)數(shù)/秒。它是軟件測(cè)試結(jié)果的測(cè)量單位。一個(gè)事務(wù)是指一個(gè)客戶(hù)機(jī)向服務(wù)器發(fā)送請(qǐng)求然后服務(wù)器做出反應(yīng)的過(guò)程??蛻?hù)機(jī)在發(fā)送請(qǐng)求時(shí)開(kāi)始計(jì)時(shí),收到服務(wù)器響應(yīng)后結(jié)束計(jì)時(shí),以此來(lái)計(jì)算使用的時(shí)間和完成的事務(wù)個(gè)數(shù)。
QPS vs TPS:QPS基本類(lèi)似于TPS,但是不同的是,對(duì)于一個(gè)頁(yè)面的一次訪(fǎng)問(wèn),形成一個(gè)TPS;但一次頁(yè)面請(qǐng)求,可能產(chǎn)生多次對(duì)服務(wù)器的請(qǐng)求,服務(wù)器對(duì)這些請(qǐng)求,就可計(jì)入“QPS”之中。如,訪(fǎng)問(wèn)一個(gè)頁(yè)面會(huì)請(qǐng)求服務(wù)器2次,一次訪(fǎng)問(wèn),產(chǎn)生一個(gè)“T”,產(chǎn)生2個(gè)“Q”。
響應(yīng)時(shí)間:執(zhí)行一個(gè)請(qǐng)求從開(kāi)始到最后收到響應(yīng)數(shù)據(jù)所花費(fèi)的總體時(shí)間,即從客戶(hù)端發(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ù)是指系統(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í)間
我們通過(guò)一個(gè)實(shí)例來(lái)把上面幾個(gè)概念串起來(lái)理解。按二八定律來(lái)看,如果每天 80% 的訪(fǎng)問(wèn)集中在 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ī)器來(lái)支持?
139 / 58 = 3
到這里,以后如果你做一般中小項(xiàng)目的前端架構(gòu),在部署自己的node服務(wù),就知道需要多少機(jī)器組成集群來(lái)匯報(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ù):
我們從中獲取幾個(gè)關(guān)鍵指標(biāo):
吞吐率(Requests per second)在圖上有顯示
服務(wù)器并發(fā)處理能力的量化描述,單位是reqs/s,指的是在某個(gè)并發(fā)用戶(hù)數(shù)下單位時(shí)間內(nèi)處理的請(qǐng)求數(shù)。某個(gè)并發(fā)用戶(hù)數(shù)下單位時(shí)間內(nèi)能處理的最大請(qǐng)求數(shù),稱(chēng)之為最大吞吐率。
記住:吞吐率是基于并發(fā)用戶(hù)數(shù)的。這句話(huà)代表了兩個(gè)含義:
a、吞吐率和并發(fā)用戶(hù)數(shù)相關(guān)
b、不同的并發(fā)用戶(hù)數(shù)下,吞吐率一般是不同的
計(jì)算公式:
總請(qǐng)求數(shù)/處理完成這些請(qǐng)求數(shù)所花費(fèi)的時(shí)間
必須要說(shuō)明的是,這個(gè)數(shù)值表示當(dāng)前機(jī)器的整體性能,值越大越好。
2、QPS每秒查詢(xún)率(Query Per Second)
每秒查詢(xún)率QPS是對(duì)一個(gè)特定的查詢(xún)服務(wù)器在規(guī)定時(shí)間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn),在因特網(wǎng)上,作為域名系統(tǒng)服務(wù)器的機(jī)器的性能經(jīng)常用每秒查詢(xún)率來(lái)衡量,即每秒的響應(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)控來(lái)獲取。
通常情況下,隨著系統(tǒng)的運(yùn)行,我們的后臺(tái)服務(wù)會(huì)產(chǎn)生各種日志,應(yīng)用程序會(huì)產(chǎn)生應(yīng)用程序的訪(fǎng)問(wèn)日志、錯(cuò)誤日志,運(yùn)行日志,網(wǎng)絡(luò)日志,我們需要一個(gè)展示平臺(tái)去展示這些日志。
后端一般都用比如ELk去展示,我們前端都是ui老手了,自己可以畫(huà)定制的UI界面,不多說(shuō)了,主要是日志本身要打印符合一定的規(guī)范,這樣格式化的數(shù)據(jù)更利于分析和展示。
并且業(yè)務(wù)邏輯型的監(jiān)控主要體現(xiàn)在日志上。通過(guò)監(jiān)控異常日志文件的變動(dòng),將新增的異常按異常類(lèi)型和數(shù)量反映出來(lái)。某些異常與具體的某個(gè)子系統(tǒng)相關(guān),監(jiān)控出現(xiàn)的某個(gè)異常也能反映出子系統(tǒng)的狀態(tài)。
在體制監(jiān)控里也能體現(xiàn)出實(shí)際業(yè)務(wù)的QPS值。觀(guān)察QPS的表現(xiàn)能夠檢查業(yè)務(wù)在時(shí)間上的分部。
此外,從訪(fǎng)問(wèn)日志中也能實(shí)現(xiàn)PV和UV的監(jiān)控。并且可以從中分析出使用者的習(xí)慣,預(yù)知訪(fǎng)問(wèn)高峰。
這個(gè)也可以通過(guò)訪(fǎng)問(wèn)日志來(lái)獲取,并且真實(shí)響應(yīng)時(shí)間是需要在controller上打log的。
監(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)單,
假如我們通過(guò)Node 提供 child_process 模塊來(lái)實(shí)現(xiàn)多核 CPU 的利用。child_process.fork() 函數(shù)來(lái)實(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')\
通過(guò) node worker.js
啟動(dòng)它,會(huì)監(jiān)聽(tīng) 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)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!