當使用Node 在生產環境作為伺服器語言時,並發量過大或程式碼問題造成OOM (out of memory) 或CPU 滿載這些都是伺服器常見的問題,此時透過監控CPU 及內存,再結合日誌及Release 就很容易發現問題。
【影片教學推薦:node js教學 】
本章將介紹如何監控本地環境及生產環境的記憶體變化
所以,如何動態監控一個Node 程序的記憶體變化呢?
以下是一個 Node Server 的範例,並且是一個有記憶體洩漏問題的範例,並且是山月在生產環境定位了很久的問題的精簡版。
那次記憶體洩漏問題中,導致單一容器中的記憶體從原先的 400M 暴漲到 700M,在 800M 的容器資源限制下偶爾會發生 OOM,導致重啟。一時沒有定位到問題 (發現問題過遲,半個月前的時序資料已被吞沒,於是未定位到 Release),於是把資源限制上調到 1000M。後來發現是由ctx.request 掛載了資料庫某個大字段而致
const Koa = require('koa') const app = new Koa() function getData () { return Array.from(Array(1000)).map(x => 10086) } app.use(async (ctx, next) => { ctx.data = getData() await next() }) app.use(ctx => { ctx.body = 'hello, world' }) app.listen(3200, () => console.log('Port: 3200'))
一些問題需要在本地及測試環境及時扼殺,來避免在生產環境造成更大的影響。那麼了解在本地如何監控記憶體就至關重要。
pidstat
是 sysstat
系列 linux 性能調試工具的一個包,竟然用它來調試 linux 的性能問題,包括內存,網絡,IO,CPU 等。
這不僅試用與node
,也適用於一切進程,包括python
,java
以及go
# -r: 指输出内存指标 # -p: 指定 pid # 1: 每一秒输出一次 # 100: 输出100次 $ pidstat -r -p pid 1 100
而在使用pidstat
之前,需要先找到進程的pid
在node
中可以透過process.pid
來找到進程的pid
> process.pid 16425
雖然透過寫程式碼可以找到pid
,但是具有侵入性,不太實用。那如何透過非侵入的手段找到 pid
呢?有兩種辦法
ps
定位進程lsof
定位進程$ node index.js shanyue # 第一种方法:通过多余的参数快速定位 pid $ ps -ef | grep shanyue root 31796 23839 1 16:38 pts/5 00:00:00 node index.js shanyue # 第二种方法:通过端口号定位 pid lsof -i:3200 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME node 31796 root 20u IPv6 235987334 0t0 TCP *:tick-port (LISTEN)
從上述程式碼可以知道,node 服務的pid 為31796
,為了可以觀察到記憶體的動態變化,再施加一個壓力測試
$ ab -c 10000 -n 1000000 http://localhost:3200/
# -r: 指输出内存指标 # -p: 指定 pid # 1: 每一秒输出一次 # 100: 输出100次 $ pidstat -r -p 31796 1 100 Linux 3.10.0-957.21.3.el7.x86_64 (shuifeng) 2020年07月02日 _x86_64_ (2 CPU) UID PID minflt/s majflt/s VSZ RSS %MEM Command 19时20分39秒 0 11401 0.00 0.00 566768 19800 0.12 node 19时20分40秒 0 11401 0.00 0.00 566768 19800 0.12 node 19时20分41秒 0 11401 9667.00 0.00 579024 37792 0.23 node 19时20分42秒 0 11401 11311.00 0.00 600716 59988 0.37 node 19时20分43秒 0 11401 5417.82 0.00 611420 70900 0.44 node 19时20分44秒 0 11401 3901.00 0.00 627292 85928 0.53 node 19时20分45秒 0 11401 1560.00 0.00 621660 81208 0.50 node 19时20分46秒 0 11401 2390.00 0.00 623964 83696 0.51 node 19时20分47秒 0 11401 1764.00 0.00 625500 85204 0.52 node
對於輸出指標的意義如下
RSS
: Resident Set Size
,常駐記憶體集,可理解為內存,這就是我們需要監控的記憶體指標VSZ
: virtual size
,虛擬記憶體從輸出可以看出,當施加了壓力測試後,記憶體由19M 漲到了85M。
pidstat
是屬於sysstat
下的linux 效能工具,但在mac 中,如何定位記憶體的變化?
此時可以使用top/htop
$ htop -p 31796
由於目前生產環境大都部署在k8s
,因此生產環境對於某個應用的記憶體監控本質上是k8s 對於某個workload/deployment
的記憶體監控,關於記憶體監控metric
的資料流向大致如下:
k8s
-> metric server
-> prometheus
-> grafana
架構圖如下:
#以上圖片取自以下文章
#最終能夠在grafana
中收集到某一應用程式的記憶體監控即時圖:
由於本部分設計內容過多,我將在以下的章節中進行介紹
這不僅適用於node 服務,而且適用於一切k8s 上的workload
本章介紹了關於Node 服務的內部存在本地環境及生產環境的監控
1、本機使用htop/top
或pidstat
監控進程記憶體
2、生產環境使用k8s/metric-server/prometheus/grafana
監控node 整個應用程式的記憶體
當監控到某一服務發生記憶體洩漏後,如何解決問題?因此接下來的文章將會講到
1、生產環境是如何監控整個應用的記憶體的
2、當生產環境發生OOM 後,如何快速定位
3、真實生產環境若干OOM 的範例定位
更多程式相關知識,可至:程式設計入門! !
以上是Node服務中如何監控本地環境及生產環境的記憶體變化?的詳細內容。更多資訊請關注PHP中文網其他相關文章!