本文章已備份在 github 上 山月的博客 歡迎 star
剛開始,先拋出一個問題:html
你知道大家生產環境的 Node 服務平時佔用內存多少嗎?或者說是多少許級?
山月在面試 Node 候選人時,這個問題足夠篩掉一半的自稱Node精通者,不過沒有回答上來,我每每會再補充一個問題,以避免漏掉優秀的無線上經驗的候選人:java
如何知道某個進程消耗多少內存?
當使用 Node 在生產環境做爲服務器語言時,併發量過大或者代碼問題形成 OOM (out of memory) 或者 CPU 滿載這些都是服務器中常見的問題,此時經過監控 CPU 及內存,再結合日誌及 Release 就很容易發現問題。node
本章將介紹如何監控本地環境及生產環境的內存變化python
因此,如何動態監控一個 Node 進程的內存變化呢?linux
如下是一個 Node Server 的示例,而且是一個有內存泄漏問題的示例,而且是山月在生產環境定位了好久的問題的精簡版。git
那次內存泄漏問題中,致使單個容器中的內存從原先的 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'))
一些問題須要在本地及測試環境獲得及時扼殺,來避免在生產環境形成更大的影響。那麼瞭解在本地如何監控內存就相當重要。github
pidstat
是 sysstat
系列 linux 性能調試工具的一個包,居然用它來調試 linux 的性能問題,包括內存,網絡,IO,CPU 等。面試
這不只試用與 node
,並且適用於一切進程,包括 python
,java
以及 go
數據庫
# -r: 指輸出內存指標 # -p: 指定 pid # 1: 每一秒輸出一次 # 100: 輸出100次 $ pidstat -r -p pid 1 100
而在使用 pidstat
以前,須要先找到進程的 pid
bash
在 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 服務的內存在本地環境及生產環境的監控
htop/top
或者 pidstat
監控進程內存k8s/metric-server/prometheus/grafana
監控 node 整個應用的內存當監控到某一服務發生內存泄漏後,如何解決問題?所以接下來的文章將會講到
本文由博客一文多發平臺 OpenWrite 發佈!