笑了,面試官問我遇到過線上問題沒有?

不知道面試的時(shí)候,面試官問你遇到過線上性能問題沒有?
GC頻繁,CPU飆高,任務(wù)隊(duì)列積壓,線程池任務(wù)拒絕等等,對(duì)于看重項(xiàng)目經(jīng)驗(yàn)的面試官,這種問題基本是標(biāo)配。
問線上問題處理的經(jīng)過,問題定位,排查的思路,怎么做的業(yè)務(wù)快速止血。
一方面考察候選人項(xiàng)目的真實(shí)性,一般遇到線上問題大部分時(shí)候是系統(tǒng)主要負(fù)責(zé)人著手處理的,所以如果你處理過線上問題,也從側(cè)面反映你的重要性。
另外還能知道面試者是不是真的從原理上掌握了問題的根本原因,對(duì)技術(shù)的熱忱等。
另外建議大家處理完線上問題,排查了原因之后不要停,把排查過程和問題原因記錄下來,一方面以后遇到類似問題可以基于已有的經(jīng)驗(yàn)快速反應(yīng),另外就是一定讓自己的知識(shí)體系化,怎么體系化呢?
就需要把日常的技術(shù)問題做歸類總結(jié)。
這篇文章主要是給大家一個(gè)參考,講講安琪拉遇到的線上問題以及排查思路。
問題描述
一個(gè)在普通不過的周末,手機(jī)突然收到線上告警短信,嚇得我一激靈,趕緊從床上爬起來打開電腦。
起因: ?消息隊(duì)列積壓了十幾萬消息,第一反應(yīng),什么情況...

趕緊穿衣服,對(duì)待線上問題要嚴(yán)肅。
如下圖,【待處…】 那一列就是指隊(duì)列中“待處理的”消息。
消息積壓,指的是消息的消費(fèi)速度跟不上生產(chǎn)的速度,消息在消息隊(duì)列中。

可以看到有好幾個(gè)分區(qū)已經(jīng)積壓了上萬條消息。
問題排查
立即開始問題排查,遇到線上問題,一定是保證最快速度止血,降低對(duì)業(yè)務(wù)的影響。
然后才是排查原因,當(dāng)然有的問題也需要快速找到原因。
第一反應(yīng)是不是入口流量太大,處理消息的線程池核心線程數(shù)滿了,任務(wù)都在排隊(duì),但是看了入口流量并沒有尖刺。
看監(jiān)控的消息消費(fèi)任務(wù)耗時(shí),如下圖:

可以看到耗時(shí)在不斷增加。那就需要看處理耗時(shí)增加原因了,為什么處理任務(wù)的耗時(shí)上漲了。
查看消息日志,如下:

發(fā)現(xiàn)有很多網(wǎng)絡(luò)接口超時(shí)的異常:

排查到這里,大致得出結(jié)論:
消息處理任務(wù)依賴下游系統(tǒng)接口,連接下游接口超時(shí),連接下游接口設(shè)置的超時(shí)時(shí)間不算短,為什么下游接口如此多SocketTimeOut呢?

恰好下游系統(tǒng)也是我負(fù)責(zé)的系統(tǒng),非常熟悉。
于是重點(diǎn)開始看下游的系統(tǒng)監(jiān)控,發(fā)現(xiàn)相關(guān)的接口調(diào)用的單機(jī)耗時(shí)時(shí)間極不規(guī)律,如下圖所示:

對(duì)比一下日常這個(gè)接口的耗時(shí)時(shí)間,如下圖,日常都沒有超過 100ms 的:

初步猜測(cè)這個(gè)地方是出現(xiàn)了問題,查看下游系統(tǒng)的監(jiān)控大盤,發(fā)現(xiàn)了問題:

老年代 GC 次數(shù)暴漲,而且 GC 耗時(shí)都到了秒級(jí)別,1 分鐘 5~10 秒的 stop the world,太恐怖了。
分析GC問題找一臺(tái)機(jī)器,把GC回收dump下來分析,使用mat查看,如下圖所示:

一共七百多M空間,一個(gè)對(duì)象就占了640M空間,找到原因了,大對(duì)象!
這個(gè)對(duì)象為什么會(huì)這么大呢?
我們用 MAT 分析一波。從 GC Roots 最短路徑如下:

解釋下,上面主要有三列:
- 第一列是內(nèi)存對(duì)象的類。
- 重點(diǎn)在二,三列,Shallow Heap 指的是對(duì)象本身占據(jù)的內(nèi)存大小,Retained Heap = 本身本身占據(jù)內(nèi)存大小 + 當(dāng)前對(duì)象可直接或間接引用到的對(duì)象的大小總和。說人話就是當(dāng)前對(duì)象如果被回收,能夠回收的內(nèi)存大小。
繼續(xù)看,第一步,查看誰引用了這個(gè)對(duì)象,找到自己代碼中的類:

第二步,查看這個(gè)對(duì)象 TaggedMetricRegistry 都引用了誰,為什么會(huì)占用這么大的內(nèi)存空間,如下圖所示:

找到罪魁禍?zhǔn)琢?,metrics 這個(gè) ?ConcurrentHashMap 占了 671M 內(nèi)存。
現(xiàn)在開始可以看下代碼,找到 ?TaggedMetricRegistry 繼承自 MetricRegistry ,metrics 是 MetricRegistry 的成員變量,如下圖:


那為什么這個(gè) ConcurrentHashMap 占了這么大的內(nèi)存空間,并且 GC 也回收不掉呢?
我們繼續(xù)看 MAT ,分析 ConcurrentHashMap ?占有的詳細(xì)內(nèi)存分布:

從上圖我們可以發(fā)現(xiàn) ConcurrentHashMap 有幾個(gè) Node 節(jié)點(diǎn)特別大。
于是繼續(xù)追下去:

看到這個(gè) key ,對(duì)應(yīng)在代碼中的位置:

這段代碼就是萬惡之源。
那么這段代碼是干嘛的呢?
它的作用是統(tǒng)計(jì)接口每次的執(zhí)行時(shí)間,它內(nèi)部 update 的源碼如下:

這個(gè)方法是統(tǒng)計(jì)接口的耗時(shí)、調(diào)用次數(shù)的。
它內(nèi)部有一個(gè) measurements 的跳躍表,存放時(shí)間戳和統(tǒng)計(jì)指標(biāo)(耗時(shí)、調(diào)用次數(shù))的鍵值對(duì)。
設(shè)置的時(shí)間窗口是 1 分鐘,也就是它會(huì)存放 1 分鐘的統(tǒng)計(jì)數(shù)據(jù)在內(nèi)存中。
當(dāng)然這里面有個(gè)采樣比,不是 1 分鐘的全量數(shù)據(jù)。
可以看到采樣比是 COLLISION_BUFFER 決定的,然后 1 分鐘上報(bào)一次內(nèi)存數(shù)據(jù)到遠(yuǎn)端。
問題就出現(xiàn)在這,因?yàn)檫@個(gè)耗時(shí)統(tǒng)計(jì)的函數(shù)的 QPS 非常高,1 分鐘有數(shù)據(jù)頻繁產(chǎn)生的時(shí)候,會(huì)導(dǎo)致在一個(gè)時(shí)間窗口(1分鐘)measurements 極速增長(zhǎng),導(dǎo)致內(nèi)存占用快速增長(zhǎng),但是因?yàn)橛袕?qiáng)引用,GC 的時(shí)候也不會(huì)把這個(gè)回收掉,所有才出現(xiàn)了上面的那個(gè)情況。
why哥說
前面就是公眾號(hào)[安琪拉的博客]的號(hào)主安琪拉給大家分享的一個(gè)線上問題排查的實(shí)操案例。
首先建議大家關(guān)注一波安琪拉,是個(gè)大佬,大廠 offer 收割了個(gè)遍。在公眾號(hào)里面分享的文章也很硬核。
然后基于他分享的這個(gè)案例,我也想簡(jiǎn)單的分享一點(diǎn)自己的看法。
第一點(diǎn)就是監(jiān)控預(yù)警系統(tǒng)的重要性。
文中的案例中的監(jiān)控系統(tǒng)就是 CAT。
CAT 是什么?
我從 github 上給大家截個(gè)圖:
https://github.com/dianping/cat

除了 CAT 之外,why哥知道的比較知名的監(jiān)控系統(tǒng)還有:
- Skywalking,專注于鏈路和性能監(jiān)控,國產(chǎn)開源,埋點(diǎn)無侵入,UI功能較強(qiáng)。能夠加入Apache孵化器,設(shè)計(jì)思想及代碼得到一定認(rèn)可,后期應(yīng)該也會(huì)有更多的發(fā)展空間及研發(fā)人員投入。目前使用廠商最多。版本更新較快。
- Pinpoint,專注于鏈路和性能監(jiān)控,韓國研發(fā)團(tuán)隊(duì)開源,埋點(diǎn)無侵入,UI功能較強(qiáng)。
- zipkin 由Twitter開源,調(diào)用鏈分析工具,基于 spring-cloud-sleuth 得到廣泛使用,非常輕量,使用部署簡(jiǎn)單。
監(jiān)控預(yù)警系統(tǒng),就是系統(tǒng)的眼睛。
所以why哥在上家公司的時(shí)候有幸深度參與了自研的監(jiān)控系統(tǒng),取名就叫做:眼睛蛇。
我取的。
第二點(diǎn)就是日志收集。
文中的案例,日志收集使用的是 ELK 體系。
不管是什么日志收集手段吧。
日志收集的意義是非常重大的。
現(xiàn)在大家都是微服務(wù)化部署,一個(gè)應(yīng)用部署到幾十個(gè)服務(wù)器上去。
如果需要登錄到每個(gè)服務(wù)器上去查詢?nèi)罩荆瑢⑹且患浅5托液臅r(shí)的事情。
而日志收集,就是一把利器,用順手了,事半功倍。
第三點(diǎn)也就是最重要的一點(diǎn):敬畏生產(chǎn)。
我的領(lǐng)導(dǎo)曾經(jīng)不止一次的給我說過:
遇到生產(chǎn)問題,第一件事千萬不要想著排查問題,而是想著怎么恢復(fù)業(yè)務(wù)。
其實(shí)上面這句話我也感覺很矛盾,不把問題排查出來了,怎么去解決問題然后恢復(fù)業(yè)務(wù)呢?
其實(shí),我們常見的一個(gè)手段就是先保留現(xiàn)場(chǎng),然后立即回滾版本。
有問題,拿到測(cè)試環(huán)境、預(yù)發(fā)布環(huán)境、災(zāi)備環(huán)境去定位,而不要在生產(chǎn)定位問題。
比如在這個(gè)案例中。
當(dāng)我們定位到是 GC 導(dǎo)致的問題時(shí),就應(yīng)該當(dāng)機(jī)立斷的先對(duì)應(yīng)用進(jìn)行重啟,然后對(duì)消息進(jìn)行消費(fèi)。
能爭(zhēng)取一點(diǎn)時(shí)間就算一點(diǎn)時(shí)間。
而我們根據(jù)保留的現(xiàn)場(chǎng),繼續(xù)定位到是這個(gè)監(jiān)控統(tǒng)計(jì)功能的問題,且這個(gè)功能確實(shí)是需要這么多的內(nèi)存的時(shí)候。
我們知道重啟是解決不了根本問題的,需要發(fā)布緊急版本,把這個(gè)統(tǒng)計(jì)功能關(guān)閉掉。
再之后,驗(yàn)證線上穩(wěn)定之后,才是去復(fù)盤分析這個(gè)生產(chǎn)問題的前因后果。
荒腔走板
前段時(shí)間有個(gè)讀者在我的公眾號(hào)后臺(tái)給我留言:

他說他站在我曾經(jīng)拍照的地方也拍了一張照片。
是的,我當(dāng)時(shí)就站在他拍的這個(gè)路牌下拍了一張照片,發(fā)在了文章里面。
只是我一個(gè)小小的、卑微的、成都的打工人,何德何能,通過一篇文章,讓別人對(duì)成都產(chǎn)生向往。
當(dāng)然,我也衷心的祝愿你,明年春暖花開的時(shí)候,現(xiàn)在大四實(shí)習(xí)的你,留在了成都自己喜歡的崗位,工位上插著一把花正旺盛的綻放著。
我主要是想要分享一下真正讓我澎湃的關(guān)于成都的一篇文章:
《什么是成都?》
這是星球研究所于 2018 年 3 月 2 日發(fā)布的一篇文章,那一天正是戊戌年正月十五,彼時(shí)我還是一個(gè)在外的游子,那天我沒有吃到元宵,但是這篇文章就是最好的“元宵”。
甚至不舍得一口氣讀完,仿佛在細(xì)品著一碗佳釀。之后又反復(fù)觀看了幾遍這篇文章,內(nèi)心產(chǎn)生了無數(shù)的遐想。
成都不是我的故鄉(xiāng),但是我仿佛是聽到了來自故鄉(xiāng)的歡呼。
引用評(píng)論中的一句話:
如若 1600 萬的成都人都能有幸閱讀到,那一定是至少 1600 萬次的澎湃與自豪。
加油哦,成都?xì)g迎你。
《什么是成都?》這篇文章分享給你,希望你能喜歡。
推薦?? :有哪些道理是我當(dāng)了程序員后才知道的?
推薦?? :沒想到你竟然是這樣的volatile!
推薦?? :這個(gè)Bug的排查之路,真的太有趣了。
推薦?? :臥槽,這年輕人。
推薦?? :我給Apache頂級(jí)項(xiàng)目貢獻(xiàn)了點(diǎn)源碼。
我是 why,一個(gè)主要寫代碼,經(jīng)常寫文章,偶爾拍視頻的程序猿。
還有,歡迎關(guān)注我呀。
轉(zhuǎn)發(fā)、點(diǎn)贊、在看、一鍵三連。

