為什麼需要效能監控?以下這篇就來帶大家了解一下Node.js效能監控,希望對大家有幫助!
#Node作為Javascript在服務端的一個執行時間(Runtime),極大的豐富了Javascript的應用場景。
但是Node.js Runtime本身就是一個黑盒,我們無法感知運行時的狀態,對於線上問題也難以復現。
因此效能監控是Node.js應用程式「正常運作」的基石。不僅可以隨時監控執行時期的各項指標,還可以幫助排除異常場景問題。
效能監控可以分為兩個部分:
效能指標的擷取與展示
#效能資料的抓取和分析
agenthub是常駐進程,用來收集效能指標並回報
整體從監控,展示,快照,分析形成閉環,接入便捷簡單,但是拓展運行時還是有風險
負責效能日誌的擷取與傳輸跟AliNode最大的差別在於使用了
#CPU
從上圖可以看出,rss
包含程式碼段(Code Segment
)、堆疊記憶體(Stack
)、堆記憶體(Heap
)
透過v8.getHeapStatistics()
和v8.getHeapSpaceStatistics()
可以取得v8堆內存和堆空間的分析數據,下圖展示了v8的堆內存組成分佈:
堆內存空間先劃分為空間(space),空間又劃分為頁(page),記憶體依照1MB對齊進行分頁。
New Space:新生代空間,用來存放一些生命週期比較短的物件數據,平分為兩個空間(空間類型為semi space
): from space
,to space
晉升的物件
Code Space:存放v8 JIT編譯後的可執行程式碼
Map Space:存放Object指向的隱藏類別的指標目標,隱藏類別指標是v8根據執行時間記錄下的物件佈局結構,用於快速存取物件成員
Large Object Space:用來存放大於1MB而無法分配到頁的物件
##v8的垃圾回收演算法分為兩類:
New space分為
from與
to
New space空間滿了
步驟:
發現存活(可達)物件
to space
中當複製結束時,
to space就被清空了
適用於回收頻繁,記憶體不大的對象,典型的空間換時間的策略,缺點是浪費了多一倍的空間
灰色:代表不可回收對象,且其所產生的引用還沒掃描完
###將V8根對象直接引用的物件放進一個###marking queue###(顯式堆疊)中,並將這些物件標記為灰色######從這些物件開始做深度優先遍歷,每存取一個對象,將該物件從###marking queue### ###pop###出來,並標記為黑色######然後將該物件引用下的所有白色物件標記為灰色,###push###到###marking queue###上,如此往復######直到堆疊上所有物件都pop掉為止,老生代的物件只剩下黑色(不可回收)和白色(可以回收)兩種了######PS:當一個物件太大,無法push到空間有限的堆疊時,v8會把這個物件保留灰色跳過,將整個堆疊標記為溢位狀態(overflowed),等堆疊清空後,再次進行遍歷標記,這樣導致需要額外掃描一遍堆###############Sweep#########清除白色物件######會造成記憶體空間不連續###############Compact###Old space
的一端,這樣清除出來的空間就是連續完整的在最開始v8進行垃圾回收時,需要停止程式的運行,掃描完整個堆,回收完內存,才會重新執行程式。這種行為就叫全停頓(Stop-The-World
)
雖然新生代活動對象較小,回收頻繁,全停頓,影響不大,但是老生代存活對像多且大,標記、清理、整理等造成的停頓就會比較嚴重。
這個理念其實有點像React框架中的Fiber架構,只有在瀏覽器的空閒時間才會去遍歷Fiber Tree執行對應的任務,否則延遲執行,盡可能少地影響主線程的任務,避免應用卡頓,提升應用效能。
由於v8對於新老生代的空間預設限制了大小
New space
預設限制:64位元系統為32M,32位元系統為16MOld space
# 預設限制: 64位元系統為1400M,32位元系統為700M因此node
提供了兩個參數用於調整新老生代的空間上限
#--max-semi-space-size
:設定New Space
空間的最大值:設定
Old Space空間的最大值
查看GC日誌
也提供了三種檢視GC日誌的方式:
--trace_gc
:一行日誌簡單描述每次GC時的時間、型別、堆大小變更和產生原因--trace_gc_verbose
:展示每次GC後每個V8堆空間的詳細狀況--trace_gc_nvp:每次GC的詳細鍵值對訊息,包含GC類型,暫停時間,記憶體變化等
Heapsnapshot
產生方式
分析方法
產生的.heapsnapshot
文件,可以在Chrome devtools工具列的Memory,選擇上傳後,展示結果如下圖:############預設的視圖是Summary
視圖,在這裡我們要關注最右邊兩欄:Shallow Size
和Retained Size
Shallow Size
:表示該物件本身在v8堆記憶體分配的大小#Retained Size
:表示該物件所有引用物件的Shallow Size
之和當發現Retained Size
特別大時,該物件內部可能存在記憶體洩漏,可以進一步展開去定位問題
還有Comparison
視圖是用來比較分析兩個不同時段的堆快照,透過Delta
列可以篩選出記憶體變化最大的物件
對於執行程式的CPU進行快照取樣,可以用來分析CPU的耗時及佔比
.cpuprofile檔案有以下幾種方式:
文件,可以在Chrome devtools工具列的Javascript Profiler
(不在預設tab,需要在工具列右側的更多中開啟顯示),選擇上傳文件後,展示結果如下圖:
預設的視圖是
Heavy視圖,在這裡我們看到有兩欄:Self Time
和Total Time
和Self Time
偏差較大時,此函數可能存在耗時比較多的CPU密集型運算,也可以展開進一步定位排查
##產生方式
node --abort-on-uncaught-exception
#gcore
## 案例分析##觀察
從監控可以觀察到堆內存在持續上升,因此需要堆快照進行排查
heapsnapshot可以分析排查到有一個
newThing的物件一直保持著比較大的記憶體
排查
方法沒有調用,但是
newThing# ##物件是引用自###theThing###,導致其一直存在於###replaceThing###這個函數的執行上下文中,沒有被釋放,這就是典型的由於閉包產生的記憶體洩漏案例# ########小結#########常見的記憶體洩漏有以下幾種情況:###因此在上述這幾種情況時,一定要謹慎考慮物件在記憶體中是否會被自動回收,不會被自動回收的話,需要手動進行回收,例如手動把物件設定為null
、移除定時器、解綁事件監聽等
至此,本文已經對整個Node.js的效能監控系統進行了詳細的介紹。
首先,介紹了效能監控解決的問題,組成部分以及主流方案的優缺點對比。
然後,針對兩大部分效能指標和快照工具進行了具體的介紹,
最後,從觀察、分析、檢查再現一個簡單的記憶體洩漏案例,並總結了常見記憶體洩漏的情況和解決方案。
希望這篇文章能幫助大家對整個Node.js的效能監控系統有所了解。
更多node相關知識,請造訪:nodejs 教學!
以上是為什麼需要效能監控?聊聊Node.js效能監控的詳細內容。更多資訊請關注PHP中文網其他相關文章!