Node.js 应用故障排查手册 —— Node.js 性能平台使用指南
楔子
前一節(jié)中我們借助于 Chrome devtools 實(shí)現(xiàn)了對(duì)線上 Node.js 應(yīng)用的 CPU/Memory 問題的排查定位,但是在實(shí)際生產(chǎn)實(shí)踐中,大家會(huì)發(fā)現(xiàn) Chrome devtools 更加偏向本地開發(fā)模式,因?yàn)轱@然 Chrome devtools 不會(huì)負(fù)責(zé)去生成分析問題所需要的 Dump 文件,這意味著開發(fā)者還得額外在線上項(xiàng)目中設(shè)置好?v8-profiler?和?heapdump?這樣的工具,并且通過額外實(shí)現(xiàn)的服務(wù)來能夠去對(duì)線上運(yùn)行的項(xiàng)目進(jìn)行實(shí)時(shí)的狀態(tài)導(dǎo)出。
加上實(shí)際上預(yù)備章中除了 CPU/Memory 的問題,我們還會(huì)遇到一些需要分析錯(cuò)誤日志、磁盤和核心轉(zhuǎn)儲(chǔ)文件等才能定位問題的狀況,因此在這些場景下,僅僅靠 Chrome devtools 顯然會(huì)有一些力不從心。正是為了解決廣大 Node.js 開發(fā)者的這些痛點(diǎn),我們?cè)谶@里推薦大家在使用?Node.js 性能平臺(tái),即原來的 AliNode,它已經(jīng)在阿里巴巴集團(tuán)內(nèi)部承載了幾乎所有的 Node.js 應(yīng)用線上運(yùn)行監(jiān)控和問題排查,因此大家可以放心在生產(chǎn)環(huán)境部署使用。
本節(jié)將從?Node.js 性能平臺(tái)?的設(shè)計(jì)架構(gòu)、核心能力以及最佳實(shí)踐等角度,幫助開發(fā)者更好地使用這一工具來解決前面提到的異常指標(biāo)分析和線上 Node.js 應(yīng)用故障定位。
本書首發(fā)在 Github,倉庫地址:https://github.com/aliyun-node/Node.js-Troubleshooting-Guide,云棲社區(qū)會(huì)同步更新。
架構(gòu)
Node.js 性能平臺(tái)其實(shí)簡單的說由三部分組成:云控制臺(tái)?+?AliNode runtime?+?Agenthub,如下圖所示:
具體的部署步驟可以查看官方文檔:自助式部署 Runtime。借助于 Node.js 性能平臺(tái)的整套解決方案,我們可以很方便地實(shí)現(xiàn)預(yù)備章節(jié)中提到的絕大部分異常指標(biāo)的告警分析的能力。在生產(chǎn)實(shí)踐過程中,實(shí)際上在筆者看來,Node.js 性能平臺(tái)解決方案其實(shí)僅僅是提供了三個(gè)最核心卻也是最有效的能力:
- 異常指標(biāo)告警,即預(yù)備節(jié)中一些異常指標(biāo)出現(xiàn)異常時(shí)能通過短信/釘釘通知到開發(fā)者
- 導(dǎo)出線上 Node.js 應(yīng)用狀態(tài),包括但不限于即前面 Chrome devtools 一節(jié)中提到的 CPU/Memory 狀態(tài)導(dǎo)出
- 在線分析結(jié)果和更好的 UI 展示,定制化解析應(yīng)用導(dǎo)出狀態(tài)和展示,更符合國內(nèi)開發(fā)者習(xí)慣
換言之,Node.js 性能平臺(tái)作為一個(gè)產(chǎn)品本身功能也在不斷迭代新增修改中,但是以上的三個(gè)核心能力一定是第一優(yōu)先級(jí)保障的,其它邊邊角角的功能則相對(duì)來說響應(yīng)優(yōu)先級(jí)沒有那么高。
實(shí)際上我們也理解作為使用平臺(tái)的開發(fā)者希望能在一個(gè)地方看到 Node.js 線上應(yīng)用從底層到業(yè)務(wù)層的所有細(xì)節(jié),然而我個(gè)人感覺不同的工具都有應(yīng)該有其核心的能力輸出,很多時(shí)候不斷做加法容易讓產(chǎn)品本身定位模糊化以及泛而不精,Node.js 性能平臺(tái)實(shí)際上始終在致力于讓原本線上黑盒的運(yùn)行時(shí)狀態(tài),能更加直觀地反饋給開發(fā)者,讓 Node.js 應(yīng)用的開發(fā)者面對(duì)一些偏向底層的線上疑難雜癥能夠不再無所適從。
最佳實(shí)踐
I. 配置合適的告警
線上應(yīng)用的告警實(shí)際上是一種自我發(fā)現(xiàn)問題的保護(hù)機(jī)制,如果沒有告警能力,那每次都會(huì)等到問題暴露到用戶側(cè)導(dǎo)致其反饋才能發(fā)現(xiàn)問題,這顯然對(duì)用戶體驗(yàn)非常的不友好。
因此部署完成一個(gè)項(xiàng)目后,開發(fā)者首先需要去配置合適的告警,而在我們的生產(chǎn)實(shí)踐中,線上問題通過錯(cuò)誤日志、Node.js 進(jìn)程 CPU/Memory 的分析、核心轉(zhuǎn)儲(chǔ)(Core dump)的分析以及磁盤分析能夠得出結(jié)論,因此我們需要的基本的告警策略也是源自以上五個(gè)部分。幸運(yùn)的是平臺(tái)已經(jīng)給我們預(yù)設(shè)好了這些告警,大家只需要選擇一下即可完整這里的告警配置,如下圖所示:
在?Node.js 性能平臺(tái)?的告警頁面上有?快速添加規(guī)則,點(diǎn)開選中后會(huì)自動(dòng)生成告警規(guī)則的閾值表達(dá)式模板和報(bào)警說明模板,我們可以按照項(xiàng)目實(shí)際監(jiān)控需求進(jìn)行修改,比如想要對(duì) Node.js 進(jìn)程的堆內(nèi)存進(jìn)行監(jiān)控,可以選中?Memory 預(yù)警?選項(xiàng),如下圖所示:
此時(shí)點(diǎn)擊?添加報(bào)警項(xiàng)?即完整了對(duì)進(jìn)程堆內(nèi)存的告警,并且將出現(xiàn)告警時(shí)需要點(diǎn)擊?通知設(shè)置->添加到聯(lián)系人列表?來添加的聯(lián)系人加入此條規(guī)則,如下圖所示:
那么在例子中的這條默認(rèn)的規(guī)則里,當(dāng)我們的 Node.js 進(jìn)程分配的堆內(nèi)存超過堆上線的 80%(默認(rèn) 64 位機(jī)器上堆上限是 1.4G)時(shí)會(huì)觸發(fā)短信通知到配置綁定到此條規(guī)則的聯(lián)系人。
實(shí)際上快速添加規(guī)則列表中給大家提供的是最常見的一些預(yù)配置好的告警策略,如果這些尚不能滿足你的需求,更多定制化的自定義的服務(wù)告警策略配置方法可以看官方文檔?報(bào)警設(shè)置。并且除了短信告警,也支持釘釘機(jī)器人推送告警消息到群,方便群發(fā)感知線上 Node.js 應(yīng)用態(tài)勢。
II. 按照告警類型進(jìn)行分析
按照 I 節(jié)中配置完成合適的告警規(guī)則后,那么當(dāng)收到告警短信時(shí)就可以按照策略類型進(jìn)行對(duì)應(yīng)的分析了。本節(jié)將按照預(yù)備節(jié)中比較常見的五大類問題來逐一講解。
a. 磁盤監(jiān)控
這個(gè)是比較好處理的問題,在快速添加的規(guī)則里實(shí)際上我們會(huì)在服務(wù)器的磁盤使用超過 85% 時(shí)進(jìn)行告警,那么收到磁盤告警后,可以連接到服務(wù)器,使用如下命令查看那個(gè)目錄占用比較高:
sudo du -h --max-depth=1 /找到占比比較高的目錄和文件后,看看是否需要備份后刪除來釋放出磁盤空間。
b. 錯(cuò)誤日志
收到特定的錯(cuò)誤日志告警后,只需要去對(duì)應(yīng)的項(xiàng)目的?Node.js 性能平臺(tái)?控制臺(tái)找到問題?實(shí)例?去查看其?異常日志?即可,如下圖所示:
這里會(huì)按照錯(cuò)誤類型進(jìn)行規(guī)整,大家可以結(jié)合展示的錯(cuò)誤棧信息來進(jìn)行對(duì)應(yīng)的問題定位。注意這里的錯(cuò)誤日志文件需要你在部署 Agenthub 的時(shí)候?qū)懭肱渲梦募?#xff0c;詳細(xì)可以參見文檔?配置和啟動(dòng) Agenthub?一節(jié)中的?詳細(xì)配置?內(nèi)容。
c. 進(jìn)程 CPU 高
終于到了前一節(jié)中借助?v8-profiler?導(dǎo)出 CPU Profile 文件再使用 Chrome devtools 進(jìn)行分析的異常類型了。那么在?Node.js 性能平臺(tái)?的整套解決方案下,我們并不需要額外的去依賴類似 v8-profiler 這樣的第三方庫來實(shí)現(xiàn)進(jìn)程狀態(tài)的導(dǎo)出,與此相對(duì)的,當(dāng)我們收到 Node.js 應(yīng)用進(jìn)程的 CPU 超過我們?cè)O(shè)置的閾值告警時(shí),我們只需要在控制臺(tái)對(duì)應(yīng)的?實(shí)例?點(diǎn)擊?CPU Profile?按鈕即可:
默認(rèn)會(huì)給抓取的進(jìn)程生成 3 分鐘的 CPU Profile 文件,等到結(jié)束后生成的文件會(huì)顯示在?文件?頁面:
此時(shí)點(diǎn)擊?轉(zhuǎn)儲(chǔ)?即可上傳到云端以供在線分析展示了,如下圖所示:
這里可以看到有兩個(gè)?分析?按鈕,其實(shí)第二個(gè)下標(biāo)帶有?(devtools)?的分析按鈕實(shí)際上就是前一節(jié)中提到的 Chrome devtools 分析,這里不再重復(fù)講解了,如果有遺忘的同學(xué)可以再去回顧下本大章前一節(jié)的內(nèi)容。我們重點(diǎn)看下第一個(gè) AliNode 定制的分析,點(diǎn)擊第一個(gè)分析按鈕后,可以在新頁面看到如下所示內(nèi)容:
這里其實(shí)也是火焰圖,但與 Chrome devtools 提供的火焰圖不一樣的地方在于,這里是將抓取的 3 分鐘內(nèi)的 JS 函數(shù)執(zhí)行進(jìn)行了聚合展示出來的火焰圖,在一些存在多次執(zhí)行同一個(gè)函數(shù)(可能每次執(zhí)行非常短)的情況下,聚合后的火焰圖可以很方便的幫助我們找到代碼的執(zhí)行瓶頸來進(jìn)行對(duì)應(yīng)的優(yōu)化。
值得一提的是,如果你使用的 AliNode runtime 版本在?v3.11.4?或者?v4.2.1?以上(包含這兩個(gè)版本)的話,當(dāng)你的應(yīng)用出現(xiàn)類死循環(huán)問題,比如由于異常的用戶參數(shù)導(dǎo)致的正則回溯(即執(zhí)行完這個(gè)正則要十幾年,類似于 Node.js 進(jìn)程發(fā)生了死循環(huán))這類問題時(shí),可以通過抓取 CPU Profile 文件來很方便地定位到問題代碼,詳細(xì)信息有興趣的同學(xué)可以看下?Node.js 性能平臺(tái)支持死循環(huán)和正則攻擊定位。
d. 內(nèi)存泄漏
與 CPU 高的問題一樣,當(dāng)我們收到 Node.js 應(yīng)用進(jìn)程的堆內(nèi)存占據(jù)堆上限的比率超過我們?cè)O(shè)置的閾值時(shí),我們也不需要類似?heapdump?這樣的第三方模塊來導(dǎo)出堆快照進(jìn)行分析,我們還是在控制臺(tái)對(duì)應(yīng)的?實(shí)例?點(diǎn)擊?堆快照?按鈕即可生成對(duì)應(yīng) Node.js 進(jìn)程的堆快照:
生成的堆快照文件同樣會(huì)顯示在?文件?列表頁面,點(diǎn)擊?轉(zhuǎn)儲(chǔ)?將堆快照上傳至云端以供接下來的分析:
與上面一樣,下標(biāo)帶有?(devtools)?的分析按鈕還是前一節(jié)中提到的 Chrome devtools 分析,這里還是著重解析下 AliNode 定制的第一個(gè)分析按鈕,點(diǎn)擊后新頁面如下圖所示:
首先解釋下上面的總覽欄目的內(nèi)容信息:
- 文件大小:?堆快照文件本身的大小
- Shallow Szie 總大小:?回顧下上一節(jié)中的內(nèi)容,GC 根的 Retained Size 大小其實(shí)就是堆大小,也等于堆上分配的所有對(duì)象的 Shallow Size 總大小,因此這里其實(shí)就是已使用的堆空間
- 對(duì)象個(gè)數(shù):?當(dāng)前堆上分配的 Heap Object 總個(gè)數(shù)
- 對(duì)象邊個(gè)數(shù):?這個(gè)稍微抽象一些,假如 Object A.b 指向另一個(gè) Object B,我們則認(rèn)為表示指向關(guān)系的 b 屬性就是一條邊
- GC Roots 個(gè)數(shù):?V8 引擎實(shí)現(xiàn)的堆分配,其實(shí)并不是我們之前為了幫助大家理解簡化的只有一個(gè) GC 根的情況,在實(shí)際的運(yùn)行模型下,堆空間內(nèi)存在許多的 GC 根,這里是真實(shí)的 GC 根的個(gè)數(shù)
這部分的信息旨在給大家一個(gè)概覽,部分信息需要深入解讀堆快照才能徹底理解,如果你實(shí)在無法理解其中的幾個(gè)概覽指標(biāo)信息,其實(shí)也無傷大雅,因?yàn)檫@并不影響我們定位問題代碼。
簡單了解了概覽信息的含義后,接著我們來看對(duì)于定位 Node.js 應(yīng)用代碼段非常重要的信息,第一個(gè)是默認(rèn)展示的?可疑點(diǎn)?信息,上圖中的內(nèi)容表示 @15249 這個(gè)對(duì)象占據(jù)了堆空間 97.41% 的內(nèi)存,那么它很可能就是一個(gè)泄漏對(duì)象,這里又存在兩種可能:
- 此對(duì)象本身應(yīng)該被釋放但是卻沒有釋放,造成堆空間占用如此大
- 此對(duì)象的某些屬性應(yīng)該被釋放但是卻沒有釋放,造成表象是此對(duì)象占據(jù)大量的堆空間
要判斷是哪一種情況,以及追蹤到對(duì)應(yīng)的代碼段,我們需要點(diǎn)擊圖中的?簇視圖?鏈接進(jìn)行進(jìn)一步觀察:
這里繼續(xù)解釋下什么是簇視圖,簇視圖實(shí)際上是支配樹的一個(gè)別名,也就是這個(gè)視圖下我們看到的正是前面一節(jié)中提到的從可疑泄漏對(duì)象出發(fā)的支配樹視圖,它的好處是,在這個(gè)視圖下,父節(jié)點(diǎn)的 Retained Size 可以直接由其子節(jié)點(diǎn)的 Retained Size 累加后再加上父節(jié)點(diǎn)自身的 Shallow Size 得到,換言之,在這個(gè)視圖下我們層層展開即可以看到可疑泄漏對(duì)象的內(nèi)存究竟被哪些子節(jié)點(diǎn)占用了。
并且結(jié)合前一節(jié)的支配樹描述,我們可以知道支配樹下的父子節(jié)點(diǎn)關(guān)系,并不一定是真正的堆上空間內(nèi)的對(duì)象父子關(guān)系,但是對(duì)于那些支配樹下父子關(guān)系在真正的堆空間內(nèi)也存在父子節(jié)點(diǎn)關(guān)系的簇節(jié)點(diǎn),我們將真正的?邊?也用淺紫色標(biāo)識(shí)出來,這部分的?邊?信息對(duì)于我們映射到真正的代碼段非常有幫助。在這個(gè)簡單的例子中,我們可以很清晰的看到可疑泄漏對(duì)象 @15249 實(shí)際上是下屬的 test-alinode.js 中存在一個(gè) array 變量,其中存儲(chǔ)了四個(gè) 45.78 兆的數(shù)組導(dǎo)致的問題,這樣就找到了問題代碼可以進(jìn)行后續(xù)優(yōu)化。
而在實(shí)際生產(chǎn)環(huán)境的堆快照分析下,很多情況下簇視圖下的父子關(guān)系在真實(shí)的堆空間中并不存在,那么就不會(huì)有這些紫色的邊信息展示,這時(shí)候我們想要知道可疑泄漏對(duì)象如何通過 JavaScript 生成的對(duì)象間引用關(guān)系引用到后面真正占據(jù)掉堆空間的對(duì)象(比如上圖中的 40 多兆的 Array 對(duì)象),我們可以點(diǎn)擊?可疑節(jié)點(diǎn)自身的地址鏈接?:
這樣就進(jìn)入到以此對(duì)象為起點(diǎn)的堆空間內(nèi)真正的對(duì)象引用關(guān)系視圖?Search 視圖:
這個(gè)視圖因?yàn)榉从车氖嵌芽臻g內(nèi)各個(gè) Heap Object 之間真正的引用連接關(guān)系,因此父對(duì)象的 Retained Size 并不能直接由子節(jié)點(diǎn)的 Retained Size 累加獲取,如上圖紅框內(nèi)的內(nèi)容,顯然這里的三個(gè)子節(jié)點(diǎn) Retained Size 累加已經(jīng)超過 100%,這也是 Search 視圖和簇視圖很大的不同點(diǎn)。借助于 Search 視圖,我們可以根據(jù)其內(nèi)反映出來的對(duì)象和邊之間的關(guān)系來定位可疑泄漏對(duì)象具體是在我們的 JavaScript 代碼中的哪一部分生成。
其實(shí)看到這邊,一些讀者應(yīng)該意識(shí)到了這里的 Search 視圖實(shí)際上對(duì)應(yīng)的就是前一節(jié)中提到的 Chrome devtools 的 Containment 視圖,只不過這里的起始點(diǎn)是我們選中的對(duì)象本身罷了。
最后就是需要提一下?Retainers 視圖,它和前一節(jié)中提到的 Chrome devtools 中解析堆快照展示結(jié)果里面的 Retainers 含義是一致的,它表示對(duì)象的父引用關(guān)系鏈,我們可以來看下:
這里 globa@1279 對(duì)象的 clearImmediate 屬性指向 timers.js()@15325,而?timers.js()@15325 的 context 屬性指向了可疑的泄漏對(duì)象 system / Context@15249。
在絕大部分的情況下,通過結(jié)合?Search 視圖?和?Retainers 視圖?我們可以定位到指定對(duì)象在 JavaScript 代碼中的生成位置,而?簇視圖?下我們又可以比較方便的知道堆空間被哪些對(duì)象占據(jù)掉了,那么綜合這兩部分的信息,我們就可以實(shí)現(xiàn)對(duì)線上內(nèi)存泄漏的問題進(jìn)行分析和代碼定位了。
e. 出現(xiàn)核心轉(zhuǎn)儲(chǔ)
最后就是收到服務(wù)器生成核心轉(zhuǎn)儲(chǔ)文件(Core dump 文件)的告警了,這表示我們的進(jìn)程已經(jīng)出現(xiàn)了預(yù)期之外的 Crash,如果你的 Agenthub 配置正常的話,在?文件?->?Coredump 文件?頁面會(huì)自動(dòng)將生成的核心轉(zhuǎn)儲(chǔ)文件信息展示出來:
和之前的步驟類似,我們想要看到服務(wù)端分析和結(jié)果展示,首先需要將服務(wù)器上生成的核心轉(zhuǎn)儲(chǔ)文件轉(zhuǎn)儲(chǔ)到云端,但是與之前的 CPU Profile 和堆快照的轉(zhuǎn)儲(chǔ)不一樣的地方在于,核心轉(zhuǎn)儲(chǔ)文件的分析需要我們提供對(duì)應(yīng) Node.js 進(jìn)程的啟動(dòng)執(zhí)行文件,即 AliNode runtime 文件,這里簡化處理為只需要設(shè)置 Runtime 版本即可:
點(diǎn)擊?設(shè)置 runtime 版本?即可進(jìn)行設(shè)置,格式為?alinode-v{x}.{y}.{z}?的形式,比如 alinode-v3.11.5,版本會(huì)進(jìn)行校驗(yàn),請(qǐng)務(wù)必填寫你的應(yīng)用真實(shí)在使用的 AliNode runtime 版本。版本填寫完成后,我們就可以點(diǎn)擊?轉(zhuǎn)儲(chǔ)?按鈕進(jìn)行文件轉(zhuǎn)儲(chǔ)到云端的操作了:
顯然對(duì)于核心轉(zhuǎn)儲(chǔ)文件來說,Chrome devtools 是沒有提供解析功能的,所以這里只有一個(gè) AliNode 定制的分析按鈕,點(diǎn)擊這個(gè)?分析?按鈕,即可以看到結(jié)果:
這里第一欄的概覽信息看文字描述就能理解其含義,所以這里就不再多做解釋了,我們來看下比較重要的默認(rèn)視圖?BackTrace 信息視圖,此視圖下展示的實(shí)際上是 Node.js 應(yīng)用在 Crash 時(shí)刻的線程信息,許多開發(fā)者認(rèn)為 Node.js 是單線程的運(yùn)行模型,其實(shí)這句話也不是完全錯(cuò)誤,更準(zhǔn)確的說法是?單主 JavaScript 工作線程,因?yàn)閷?shí)際上 Node.js 還會(huì)開啟一些后臺(tái)線程來處理諸如 GC 里的部分任務(wù)。
絕大部分的情況下,應(yīng)用的 Crash 都是由 JavaScript 工作線程引發(fā)的,因此我們需要關(guān)注的也僅僅是這個(gè)線程,這里顯然 BackTrace 信息視圖中將 JavaScript 工作線程做了標(biāo)紅和置頂處理,展開后可以看到 Node.js 應(yīng)用 Crash 那一刻的錯(cuò)誤堆棧信息:
因?yàn)榫退阍?JavaScript 的工作線程中,也會(huì)存在 Native C/C++ 代碼的穿透,但是在問題排查中我們往往只需要去看同樣標(biāo)紅的 JavaScript 棧信息即可,像在這個(gè)簡單的例子中,顯然 Crash 是因?yàn)橐晥D去啟動(dòng)一個(gè)不存在的 JS 文件導(dǎo)致的。
值得一提的是,核心轉(zhuǎn)儲(chǔ)文件的分析功能非常的強(qiáng)大,因?yàn)樵陬A(yù)備節(jié)中我們提到其生成的途徑除了 Node.js 應(yīng)用 Crash 的時(shí)候由系統(tǒng)內(nèi)核控制輸出外,還可以由?gcore?這樣的命令手動(dòng)強(qiáng)制輸出,而本小節(jié)我們又看到核心轉(zhuǎn)儲(chǔ)文件的分析實(shí)際上可以看到此刻的 JavaScript 棧信息以及其入?yún)?#xff0c;結(jié)合這兩點(diǎn),我們可以在線上出現(xiàn) CPU Profile 一節(jié)中提到的類死循環(huán)問題時(shí)直接采用?gcore?生成核心轉(zhuǎn)儲(chǔ)文件,然后上傳至平臺(tái)云端進(jìn)行分析,這樣不僅可以看到我們的 Node.js 應(yīng)用是阻塞在哪一行的 JavaScript 代碼,甚至引發(fā)阻塞的參數(shù)我們也能完整獲取到,這對(duì)本地復(fù)現(xiàn)定位問題的幫助無疑是無比巨大的。
結(jié)尾
本節(jié)其實(shí)給大家介紹了?Node.js 性能平臺(tái)?的整套面向 Node.js 應(yīng)用開發(fā)的監(jiān)控、告警、分析和定位問題的解決方案的架構(gòu)和最佳實(shí)踐,希望能讓大家對(duì)平臺(tái)的能力和如何更好地結(jié)合自身項(xiàng)目進(jìn)行使用有一個(gè)整體的理解。
限于篇幅,最佳實(shí)踐中的 CPU Profile、堆快照和核心轉(zhuǎn)儲(chǔ)文件的分析例子都非常的簡單,這部分的內(nèi)容也更多的是旨在幫助大家理解平臺(tái)提供的工具如何使用以及其分析結(jié)果展示的指標(biāo)含義,那么本書的第三節(jié)中,我們會(huì)通過一些實(shí)際的生產(chǎn)遇到的案例問題借助于?Node.js 性能平臺(tái)?提供的上述工具分析過程,來幫助大家更好的理解這部分信息,也希望大家在讀完這些內(nèi)容后能有所收獲,能對(duì) Node.js 應(yīng)用在生產(chǎn)中的使用更有信心。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的Node.js 应用故障排查手册 —— Node.js 性能平台使用指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spark in action on K
- 下一篇: Andrew Ng教你如何引领公司进入A