以下文章來(lái)源于阿里云開(kāi)發(fā)者,作者竹一
導(dǎo)讀
一個(gè)特殊請(qǐng)求引發(fā)服務(wù)器內(nèi)存用量暴漲進(jìn)而導(dǎo)致進(jìn)程 OOM 的慘案。
問(wèn)題背景
埋點(diǎn)網(wǎng)關(guān)是螞蟻基于 nginx 開(kāi)發(fā)的接入網(wǎng)關(guān)應(yīng)用,作為應(yīng)用接入層網(wǎng)關(guān)負(fù)責(zé)移動(dòng)端埋點(diǎn)數(shù)據(jù)采集,從去年年底開(kāi)始有偶現(xiàn)的進(jìn)程 crash 問(wèn)題。
好在 nginx 設(shè)計(jì)中 worker 進(jìn)程閃退后 master 進(jìn)程會(huì)重新拉起新的進(jìn)程處理請(qǐng)求,埋點(diǎn)客戶(hù)端也有重試機(jī)制,偶現(xiàn)閃退沒(méi)有造成大的影響。
初步分析
說(shuō)實(shí)話(huà)作為 C 語(yǔ)言應(yīng)用,crash 也沒(méi)什么好奇怪的 :),第一反應(yīng)當(dāng)然是業(yè)務(wù)代碼有問(wèn)題,查看機(jī)器內(nèi)存的占用也沒(méi)有大的起伏。
所以先排除了內(nèi)存泄漏最終 OOM 導(dǎo)致進(jìn)程閃退。大概率是內(nèi)存沒(méi)用好,內(nèi)存越界訪(fǎng)問(wèn)導(dǎo)致的。這種問(wèn)題排查起來(lái)也挺簡(jiǎn)單,找部分機(jī)器開(kāi)啟 core-dump,拿到 core 文件一看就知道是哪里跪了。說(shuō)干就干,線(xiàn)上找了部分機(jī)器開(kāi)啟開(kāi)關(guān),等問(wèn)題復(fù)現(xiàn)后登錄,就遇到了第一個(gè)難題:沒(méi)有生成核心轉(zhuǎn)儲(chǔ)文件。
反復(fù)檢查 core-dump 開(kāi)關(guān)確認(rèn)已經(jīng)正確打開(kāi),再回頭檢查了一遍最近的代碼變更,也沒(méi)看出什么疑點(diǎn),這時(shí)候就有點(diǎn)一籌莫展了。
如果不是
在走迷宮時(shí),如果發(fā)現(xiàn)前面無(wú)路可走,就得回頭思考前面哪一步是不是走錯(cuò)了。
一開(kāi)始排除了內(nèi)存泄漏導(dǎo)致的 OOM 問(wèn)題,是因?yàn)閺谋O(jiān)控上看內(nèi)存占用水位只有 40% 不到,并沒(méi)有上漲到內(nèi)存用完。然而這里的監(jiān)控是分鐘級(jí)的,如果內(nèi)存在短時(shí)間內(nèi)暴漲,秒級(jí)尖刺體現(xiàn)到分鐘級(jí)監(jiān)控上很可能被平均值抹平。
再結(jié)合沒(méi)有產(chǎn)生 core-dump 文件的現(xiàn)象,如果是內(nèi)存耗盡導(dǎo)致進(jìn)程被 oom-killer 進(jìn)程殺死是說(shuō)得通的。因?yàn)閛om-killer 進(jìn)程使用SIGKILL信號(hào)強(qiáng)制殺死進(jìn)程,查看 Linux 信號(hào)手冊(cè),根據(jù) POSIX.1-1990 標(biāo)準(zhǔn),SIGKILL信號(hào)意味著進(jìn)程被強(qiáng)制結(jié)束并且不進(jìn)行核心轉(zhuǎn)儲(chǔ)。
Signal Standard Action Comment ──────────────────────────────────────────────────────────────────────── ... SIGIOT - Core IOT trap. A synonym for SIGABRT SIGKILL P1990 Term Kill signal SIGLOST - Term File lock lost (unused) ...瞌睡遇上枕頭,剛好發(fā)現(xiàn)監(jiān)控平臺(tái)上線(xiàn)了單機(jī)秒級(jí)監(jiān)控(感謝平臺(tái)工具給力),再找到發(fā)生 crash 的機(jī)器和時(shí)間點(diǎn),發(fā)現(xiàn)推測(cè)是對(duì)的,在幾秒內(nèi)其中一個(gè) worker 進(jìn)程內(nèi)存占用飆升,從幾百 MB 一路暴漲到十幾 GB,在 8C16G 規(guī)格的機(jī)器上很快就因?yàn)閮?nèi)存耗盡被內(nèi)核殺掉。
問(wèn)題查到這里,好消息是排查方向總算對(duì)了,壞消息是 OOM 進(jìn)程閃退只是問(wèn)題的表現(xiàn),而導(dǎo)致內(nèi)存飆升的根本原因還是沒(méi)什么頭緒。
懷疑有異常的攻擊流量,然而查看閃退前后該機(jī)器的網(wǎng)絡(luò)流量,inbytes 和 outbytes 并沒(méi)有波動(dòng),所以也基本排除了被突發(fā)流量攻擊;懷疑是網(wǎng)關(guān)上 ip geo 信息查詢(xún)的二分查找邏輯有死循環(huán),經(jīng)過(guò)代碼檢查和測(cè)試也沒(méi)發(fā)現(xiàn)這里有問(wèn)題;甚至懷疑系統(tǒng)跑久了有內(nèi)存碎片,但經(jīng)過(guò)排查也排除了這種可能,今年之前也沒(méi)出現(xiàn)這種問(wèn)題。
所以目前的情況就是在沒(méi)有任何外部攻擊的情況下,系統(tǒng)內(nèi)存突然就爆了。這還真是見(jiàn)了鬼,排查了這么多問(wèn)題,如此詭異的情況也是少見(jiàn)。
core-dump!
core-dump 文件是進(jìn)程閃退前最后的“遺照”,類(lèi)似尸檢之于法醫(yī),對(duì)于查問(wèn)題能提供非常多線(xiàn)索。拿不到轉(zhuǎn)儲(chǔ)文件真是兩眼一抹黑 —— 全靠猜。所以痛定思痛,決定想辦法把 core-dump 文件拿到。
既然閃退是因?yàn)閮?nèi)存占用過(guò)高,而被 oom-killer 殺死又不會(huì)進(jìn)行核心轉(zhuǎn)儲(chǔ),總不能到 Linux 內(nèi)核里修改 oom-killer 發(fā)送的信號(hào)。在跟師兄討論時(shí),師兄提出一個(gè)思路:在用戶(hù)態(tài)實(shí)現(xiàn)一個(gè) oom-killer(青春版),當(dāng)然沒(méi)有復(fù)雜的打分邏輯,只需要檢測(cè)目標(biāo)進(jìn)程的內(nèi)存用量,到閾值之后發(fā)送一個(gè)可以產(chǎn)生內(nèi)核轉(zhuǎn)儲(chǔ)行為的信號(hào)來(lái)殺死進(jìn)程,通過(guò)主動(dòng)殺死進(jìn)程的方式產(chǎn)生 core-dump 文件。
后面師兄抽空幫忙寫(xiě)了一個(gè) nginx 輔助進(jìn)程,邏輯是每秒檢測(cè)一次所有 worker 進(jìn)程的內(nèi)存用量,如果超過(guò)一定閾值就發(fā)送SIGABORT信號(hào)主動(dòng)殺死對(duì)應(yīng)進(jìn)程。當(dāng)然為了防止工具誤殺導(dǎo)致更嚴(yán)重的問(wèn)題,限制在應(yīng)用重啟后的生命周期內(nèi)最多只會(huì)觸發(fā)一次。
找了部分機(jī)器部署之后,還真給拿到了 core-dump 文件,不過(guò)還有個(gè)小插曲,第一次拿到的文件過(guò)大發(fā)生了截?cái)?,后續(xù)又將單進(jìn)程的內(nèi)存閾值從 8GB 調(diào)整為 4GB,終于拿到了完整可用的 core-dump!
如上圖可以看到程序的堆棧,這種通過(guò)自殺產(chǎn)生的內(nèi)核堆棧不像內(nèi)存越界的堆棧直接指向了程序崩潰點(diǎn),當(dāng)前的堆棧只能反應(yīng)程序在異常時(shí)執(zhí)行的代碼,不一定是準(zhǔn)確的問(wèn)題點(diǎn),但也能提供非常多的線(xiàn)索。從堆棧結(jié)合代碼可以看出程序正在進(jìn)行數(shù)據(jù)攢批寫(xiě)出, 再往前是 schema 埋點(diǎn)數(shù)據(jù)的拆分,攢批寫(xiě)出時(shí)恰好在調(diào)用 ngx_pcalloc 函數(shù)從內(nèi)存池中申請(qǐng)內(nèi)存,所以很可能是在 schema 埋點(diǎn)數(shù)據(jù)拆分之后的攢批發(fā)送時(shí)內(nèi)存分配出了問(wèn)題。
合理猜測(cè)
在繼續(xù)分析之前插入一個(gè)我們的業(yè)務(wù)流程,大致可以分為請(qǐng)求接收、數(shù)據(jù)處理、數(shù)據(jù)攢批、數(shù)據(jù)發(fā)送幾個(gè)階段,為了保護(hù)埋點(diǎn)網(wǎng)關(guān),在這些階段分別設(shè)置了數(shù)據(jù)大小限制:
數(shù)據(jù)解壓前的 body 大小限制 4MB 以?xún)?nèi);
解壓后的數(shù)據(jù)限制 32MB 以?xún)?nèi);
而拆分后單條埋點(diǎn)大小限制根據(jù)業(yè)務(wù)類(lèi)型動(dòng)態(tài)調(diào)整,最大支持 2MB;
既然程序申請(qǐng)了這么多內(nèi)存,也拿到了 core-dump,直接將內(nèi)存 dump 出來(lái)看看里面都裝了些什么數(shù)據(jù),根據(jù)數(shù)據(jù)的內(nèi)容可以大概推測(cè)是哪個(gè)節(jié)點(diǎn)申請(qǐng)的內(nèi)存。再將之前的 core-dump 文件翻出來(lái)尋找蛛絲馬跡,從內(nèi)存中看到大量攢批完成準(zhǔn)備發(fā)送的日志內(nèi)容,說(shuō)明很可能是數(shù)據(jù)攢批發(fā)送階段占用了大量?jī)?nèi)存。
數(shù)據(jù)從攢批到發(fā)送階段的內(nèi)存管理使用了內(nèi)存池,開(kāi)始攢批時(shí)創(chuàng)建內(nèi)存池,在攢批完成后會(huì)將數(shù)據(jù)打包為 HTTP 協(xié)議發(fā)送出去,期間會(huì)經(jīng)過(guò) ProtoBuf 序列化、壓縮、生成簽名等流程,最后數(shù)據(jù)寫(xiě)出成功后將內(nèi)存池整體釋放。
仔細(xì)分析這里內(nèi)存相關(guān)的動(dòng)作,有一個(gè)問(wèn)題是內(nèi)存的分配比較粗曠,因?yàn)橛胁糠謹(jǐn)?shù)據(jù)有單條超大埋點(diǎn)的需求,比如客戶(hù)端閃退堆棧數(shù)據(jù),在數(shù)據(jù)攢批階段為了保證每次攢批至少能存放一條以上的數(shù)據(jù),所以?xún)?nèi)存池創(chuàng)建時(shí)的最低大小設(shè)置為攢批閾值 + 單條埋點(diǎn)最大限制 + 部分協(xié)議元數(shù)據(jù)大小,最終這個(gè)值大約是 3MB,意味著創(chuàng)建一個(gè)寫(xiě)出請(qǐng)求至少會(huì)申請(qǐng) 3MB 內(nèi)存。但正常情況下數(shù)據(jù)發(fā)送相對(duì)數(shù)據(jù)流入的數(shù)量級(jí)會(huì)少很多,寫(xiě)出請(qǐng)求的創(chuàng)建也會(huì)隨著請(qǐng)求流入和數(shù)據(jù)攢批打散,內(nèi)存池在數(shù)據(jù)寫(xiě)出完成后就會(huì)釋放,內(nèi)存的輪轉(zhuǎn)速度非???,所以網(wǎng)關(guān)的內(nèi)存占用并不高,僅有 30% 左右。
將目光轉(zhuǎn)向內(nèi)存池的釋放階段,該階段是在 HTTP 數(shù)據(jù)發(fā)送完成并收到響應(yīng)后做的,沒(méi)有提前釋放是因?yàn)槿魯?shù)據(jù)寫(xiě)出失敗,網(wǎng)關(guān)需要將數(shù)據(jù)暫存到內(nèi)存或磁盤(pán)中,在后續(xù)進(jìn)行重試,看起來(lái)好像也沒(méi)有什么地方會(huì)有發(fā)生急性?xún)?nèi)存泄漏。
但考慮極端情況,如果前面的數(shù)據(jù)攢批速度遠(yuǎn)超數(shù)據(jù)寫(xiě)出呢?會(huì)一瞬間創(chuàng)建大量寫(xiě)出請(qǐng)求,而數(shù)據(jù)發(fā)送到下游,同機(jī)房的一個(gè) rt 大約 20ms,如果從上??鐧C(jī)房調(diào)用到河源,一個(gè) rt 就需要 40ms 了,若數(shù)據(jù)還沒(méi)來(lái)得及寫(xiě)出完成并釋放內(nèi)存池,理論上有可能導(dǎo)致內(nèi)存占用飆升。但從之前的分析看,問(wèn)題機(jī)器上并沒(méi)有大量數(shù)據(jù)涌入,若是單個(gè)請(qǐng)求過(guò)大,對(duì)于單個(gè)請(qǐng)求還有 4MB 的數(shù)據(jù)大小限制,怎么才能一瞬間將整個(gè)內(nèi)存超過(guò) 10GB 的空間打滿(mǎn)?
四兩撥千斤
以上都是猜測(cè),既然懷疑是這里,干脆就加監(jiān)控指標(biāo)發(fā)上去看看內(nèi)存究竟申請(qǐng)了多少。上線(xiàn)后發(fā)現(xiàn)在問(wèn)題機(jī)器閃退的時(shí)間點(diǎn),創(chuàng)建寫(xiě)出請(qǐng)求的數(shù)量確實(shí)出現(xiàn)了一個(gè)明顯尖刺,由于之前增加了進(jìn)程內(nèi)存限制,這里還沒(méi)有漲更高就因?yàn)橛|發(fā)閾值被殺死。到這里問(wèn)題的直接原因算是定位到了:短時(shí)間內(nèi)創(chuàng)建了大量數(shù)據(jù)寫(xiě)出請(qǐng)求,內(nèi)存池來(lái)不及釋放,導(dǎo)致內(nèi)存瞬間被打爆。
打破砂鍋問(wèn)到底,又是什么場(chǎng)景下會(huì)集中創(chuàng)建寫(xiě)出請(qǐng)求呢??jī)煞N可能:
有大量上報(bào)請(qǐng)求流入。之前也提到過(guò),從單機(jī)的網(wǎng)絡(luò)流量監(jiān)控來(lái)看,問(wèn)題時(shí)間點(diǎn)并沒(méi)有波動(dòng),并且這臺(tái)機(jī)器上的其他 worker 進(jìn)程也沒(méi)有問(wèn)題,所以基本可以排除第一種場(chǎng)景。
單次上報(bào)請(qǐng)求中攜帶了非常多數(shù)據(jù)。而對(duì)于單次請(qǐng)求,網(wǎng)關(guān)有設(shè)置 4MB 的原始數(shù)據(jù)限制,攜帶超過(guò) 4MB 的數(shù)據(jù)上報(bào)會(huì)被直接拒絕服務(wù)。難道這不到 4MB 的數(shù)據(jù)經(jīng)過(guò)一系列處理和攢批,真就撬動(dòng)了超 10GB 的內(nèi)存消耗?
從之前的內(nèi)存 dump 中又發(fā)現(xiàn)了可疑的地方,一個(gè)用戶(hù)的 uid 在內(nèi)存里重復(fù)了 6 萬(wàn)次!再細(xì)看重復(fù)的數(shù)據(jù),大部分字段都是相同的,僅有 timestamp、startTime、endTime 等時(shí)間戳字段不同。到這里第一時(shí)間想到的是一種攻擊方式——壓縮炸彈。大量重復(fù)字符,意味著更高的數(shù)據(jù)壓縮率,因?yàn)椴徽撌?LZ77 算法、哈夫曼編碼還是字典編碼,壓縮算法的核心都是利用各種手段減少重復(fù)數(shù)據(jù)占用的存儲(chǔ)空間。
正常線(xiàn)上的請(qǐng)求壓縮率根據(jù)業(yè)務(wù)上報(bào)策略的差異平均會(huì)在 30% 左右,而如果數(shù)據(jù)大量重復(fù),這個(gè)壓縮率則會(huì)非常高。根據(jù) dump 出來(lái)的數(shù)據(jù),簡(jiǎn)單擼了個(gè)腳本手動(dòng)構(gòu)造出類(lèi)似的測(cè)試數(shù)據(jù),時(shí)間戳隨機(jī)遞增,其他耗時(shí)相關(guān)的字段取隨機(jī)數(shù),剩余字段用固定 mock 值。
執(zhí)行結(jié)果如下,單條埋點(diǎn)經(jīng)過(guò) ProtoBuf 序列化后為 3.47KB,一萬(wàn)條埋點(diǎn)打包后原始數(shù)據(jù)有 34.7MB,壓縮后只剩 1.2MB,壓縮率達(dá)到恐怖的 3.5%,這就能解釋為何前面有 4MB 的 body 大小限制但沒(méi)能防住超大數(shù)據(jù)上報(bào)。
origin data bytes: 34697723 compressed data bytes: 1214252
真相大白
將 mock 出的原始數(shù)據(jù)裁剪到 32MB 以?xún)?nèi)再發(fā)送到埋點(diǎn)網(wǎng)關(guān),果然復(fù)現(xiàn)了內(nèi)存暴漲并閃退的問(wèn)題。埋點(diǎn)網(wǎng)關(guān)對(duì)于文本類(lèi)埋點(diǎn)有單次請(qǐng)求最多攜帶的埋點(diǎn)條數(shù)限制,而對(duì)于 ProtoBuf 類(lèi)型的 schema 埋點(diǎn)還沒(méi)有做限制。于是在生產(chǎn)環(huán)境先增加了對(duì)超量 schema 埋點(diǎn)上報(bào)的告警,發(fā)現(xiàn)確實(shí)存在零星攜帶超量埋點(diǎn)的請(qǐng)求,接著再對(duì) schema 類(lèi)型的埋點(diǎn)增加了條數(shù)限制后果然再?zèng)]有閃退,可以確認(rèn)根本原因是這里了。
但話(huà)說(shuō)回來(lái),這次上報(bào)雖然日志條數(shù)非常多,就算有重復(fù)數(shù)據(jù)的壓縮率高問(wèn)題,解壓后最多也就 32MB 的原始數(shù)據(jù),又是如何放大到超過(guò) 10GB 呢?
答案也在 dump 出的數(shù)據(jù)內(nèi)容中,可以看到大量重復(fù)數(shù)據(jù)的埋點(diǎn)業(yè)務(wù)碼,對(duì)應(yīng)業(yè)務(wù)對(duì)數(shù)據(jù)的時(shí)效性要求非常高,所以數(shù)據(jù)攢批閾值設(shè)置得很小,每攢夠 25.6KB 即會(huì)觸發(fā)一次日志寫(xiě)出。意味著一個(gè) 32MB 原始數(shù)據(jù)的請(qǐng)求上來(lái),在數(shù)據(jù)攢批發(fā)送時(shí)會(huì)瞬間創(chuàng)建出大約 1250 個(gè)寫(xiě)出請(qǐng)求,每個(gè)寫(xiě)出請(qǐng)求的內(nèi)存池至少 3MB,就會(huì)申請(qǐng)出總計(jì) 3.75GB 的內(nèi)存。
話(huà)又說(shuō)回來(lái),3.75GB 離 10GB 還是差很遠(yuǎn),因?yàn)檫€沒(méi)完,端特征埋點(diǎn)因?yàn)橛袑?shí)時(shí)消費(fèi)需求,所以網(wǎng)關(guān)會(huì)同時(shí)寫(xiě)出三份數(shù)據(jù),一份寫(xiě)出到 SLS,還有兩份分別發(fā)送到不同的應(yīng)用系統(tǒng),每個(gè)寫(xiě)出通道都有獨(dú)立的數(shù)據(jù)攢批發(fā)送流程,最終申請(qǐng)的內(nèi)存大小就是 3.75GB * 3 = 11.25GB。
排查到這里,問(wèn)題的原因鏈條就比較完整了:
單次請(qǐng)求攜帶大量埋點(diǎn)數(shù)據(jù),因?yàn)橹貜?fù)字段多壓縮率足夠高,所以繞過(guò)了前面對(duì)請(qǐng)求 body 的尺寸限制;
埋點(diǎn)網(wǎng)關(guān)在數(shù)據(jù)攢批發(fā)送階段的內(nèi)存池分配粗曠,默認(rèn)按鏈路的最大閾值來(lái)分配內(nèi)存,并且內(nèi)存池釋放依賴(lài)請(qǐng)求寫(xiě)出完成,內(nèi)存釋放速度遠(yuǎn)小于數(shù)據(jù)流入速度;
高時(shí)效、多份寫(xiě)出的業(yè)務(wù)特性,更是讓原本粗曠的內(nèi)存管理雪上加霜,這些因素疊加在一起,最終撬動(dòng)了超過(guò) 10GB 的內(nèi)存消耗;
話(huà)又又又說(shuō)回來(lái),以前為什么沒(méi)有出現(xiàn)這個(gè)情況?
因?yàn)槁顸c(diǎn)網(wǎng)關(guān)的數(shù)據(jù)大小限制經(jīng)歷了幾次調(diào)整,為了支持客戶(hù)端閃退這類(lèi)超大埋點(diǎn)的上報(bào),網(wǎng)關(guān)分別將數(shù)據(jù)大小限制從壓縮后 2MB、解壓后 16MB、單條埋點(diǎn) 256KB 調(diào)整到了當(dāng)前的壓縮后 4MB、解壓后 32MB、單條埋點(diǎn)限制支持根據(jù)業(yè)務(wù)動(dòng)態(tài)調(diào)整,也就間接達(dá)成了原因鏈條里的第二個(gè)因素。
解決方案
之前為 schema 埋點(diǎn)增加了單次請(qǐng)求最多攜帶的埋點(diǎn)條數(shù)限制,閃退問(wèn)題雖然已經(jīng)解決,但排查下來(lái)可以發(fā)現(xiàn)閃退是各種因素疊加在一起導(dǎo)致的結(jié)果,這些地方都還有優(yōu)化空間,對(duì)于埋點(diǎn)網(wǎng)關(guān)這種百萬(wàn) QPS 的在線(xiàn)服務(wù),性能和穩(wěn)定性的優(yōu)化非常有必要。
對(duì)于數(shù)據(jù)攢批發(fā)送,內(nèi)存池很大一部分空間被原始數(shù)據(jù)占用,其實(shí)原始數(shù)據(jù)在經(jīng)過(guò) Protobuf 序列化及壓縮后就不再需要了,因?yàn)?HTTP 請(qǐng)求發(fā)送和后續(xù)的失敗緩存使用的都是壓縮后數(shù)據(jù)。原始數(shù)據(jù)使用的這塊內(nèi)存可以提前到請(qǐng)求發(fā)送之前就釋放,不用等待請(qǐng)求結(jié)束才能釋放內(nèi)存。而壓縮之后的數(shù)據(jù)量大約只有原始數(shù)據(jù)的十分之一,大幅提升內(nèi)存的輪轉(zhuǎn)效率。
內(nèi)存的分配其實(shí)也可以更精細(xì),之前為每個(gè)寫(xiě)出請(qǐng)求分配了 3MB 內(nèi)存,是為了支持單條超大埋點(diǎn),例如客戶(hù)端閃退埋點(diǎn)一條最大可能達(dá)到 2MB,為了保證攢批時(shí)至少能存一條埋點(diǎn),并且網(wǎng)關(guān)的內(nèi)存資源比較寬裕,這塊內(nèi)存池創(chuàng)建得很大,實(shí)際使用中大部分業(yè)務(wù)攢批都用不到這么大的內(nèi)存,可以改為根據(jù)攢批數(shù)據(jù)量動(dòng)態(tài)擴(kuò)容。
除了這些縫縫補(bǔ)補(bǔ),我們也在探索使用內(nèi)存安全的語(yǔ)言比如 Rust 來(lái)實(shí)現(xiàn)更多能力,這里不過(guò)多展開(kāi)。
小結(jié)
歷時(shí)半年之久,經(jīng)過(guò)反復(fù)猜測(cè)、修改、驗(yàn)證,終于將網(wǎng)關(guān)上這個(gè)“定時(shí)炸彈”成功拆除,在成功復(fù)現(xiàn)并定位到根因后真是長(zhǎng)舒一口氣,總結(jié)下來(lái)一點(diǎn)小小的心得(主要還是心理層面的,技術(shù)方面還需要一題一議,不具有普適參考價(jià)值):
堅(jiān)信任何現(xiàn)象都有其背后的原因,在排查時(shí)苦于找不到方向,屢次道心破碎想過(guò)放棄,但線(xiàn)上的閃退告警時(shí)刻提醒著“革命尚未成功,同志仍需努力”。
沒(méi)有思路時(shí)可以拿出來(lái)和別人討論案情,思維碰撞中往往會(huì)有靈光乍現(xiàn)。
大膽假設(shè),小心求證。通過(guò)現(xiàn)象推測(cè)可能的原因并一一驗(yàn)證,同時(shí)要有將之前的假設(shè)都推翻重來(lái)的勇氣。
-
網(wǎng)關(guān)
+關(guān)注
關(guān)注
9文章
4506瀏覽量
51171 -
服務(wù)器
+關(guān)注
關(guān)注
12文章
9204瀏覽量
85547 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3029瀏覽量
74103 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7605瀏覽量
137000
原文標(biāo)題:“四兩撥千斤”——1.2MB數(shù)據(jù)如何吃掉10GB內(nèi)存
文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論