全鏈路監(jiān)控分析實戰(zhàn)(二)
告別野路子,
性能大牛錘煉之路從這里開始

面試性能崗位必問知識點:
最最常見的性能瓶頸話題:
無論給服務(wù)器多大壓力,服務(wù)器的CPU利用率始終很低,吞吐量一直上不去?如果瓶頸是由于代碼問題導(dǎo)致的,請問如何定位?
1、壓測服務(wù)器
單場景壓測被測系統(tǒng)的登錄接口,壓力曲線模型如下:
壓測策略:
施壓20個線程,每30秒增加2個線程,重點關(guān)注壓力增加的這段。
監(jiān)控平臺:
grafana+prometheus+node_exporter+influxdb

2、性能指標監(jiān)控

基本分析:壓力在不斷增大(上圖右側(cè)曲線),但吞吐量卻始終保持在2.6/s(上圖左側(cè)曲線),非常的小,而響應(yīng)時間(上圖下方曲線)卻在快速變長,性能瓶頸明顯地暴露出來。
再來看一下操作系統(tǒng)的資源消耗情況,如下圖,cpu的利用率非常低,接下來進行代碼瓶頸定位。

3、JVM核心知識梳理
如果對這些JVM的核心知識完全不懂,也不愿意進一步研究,要么果斷放棄,要么看之前的系列文章。下面這些知識不難,但是必須懂哦!
棧是線程私有的,堆是線程共享的
棧是運行時單位,堆是存儲單位
棧解決程序運行問題,堆解決數(shù)據(jù)存儲問題
堆中存的是對象,棧中存的基本數(shù)據(jù)類型和堆中對象的引用
棧代表了處理邏輯,而堆代表了數(shù)據(jù)
??臻g不足拋出異常:java.lang.StackOverflowError
堆空間不足拋出異常:java.lang.OutOfMemoryError
線程是cpu的基本執(zhí)行單元,而線程的執(zhí)行信息又存儲在??臻g里,所以我們對cpu資源的分析核心就是棧數(shù)據(jù)的分析,也就是經(jīng)常說的對線程做dump(拍快照)。
cpu常見的瓶頸主要有兩種:
cpu資源很容易被消耗掉,導(dǎo)致cpu資源利用率超高
不管給多大壓力,cpu的資源利用率總是上不去
這些問題分析的入口基本都是對棧的分析,所以棧善于分析如下問題:
系統(tǒng)無緣無故cpu過高
系統(tǒng)掛起,無響應(yīng)
系統(tǒng)運行越來越慢
性能瓶頸,如無法充分利用cpu等
線程死鎖、死循環(huán),餓死等
線程數(shù)量太多導(dǎo)致系統(tǒng)失敗,如無法創(chuàng)建線程等
4、瓶頸問題分析
壓力上不去,拋開其它因素,假設(shè)就是代碼的問題,說明線程被阻塞了,得不到cpu的執(zhí)行。在Java虛擬機層面,線程的狀態(tài)主要有:阻塞、等待、休眠、可運行。敲重點:只有處于可運行狀態(tài)的線程才可能消耗cpu,處于其它狀態(tài)的線程對cpu幾乎都沒有壓力。而現(xiàn)在的瓶頸就是cpu沒壓力呀,所以通過分析線程棧就可以知道線程正在做的事情了。
5、借助工具查找瓶頸
最強悍的工具終于上場了——arthas,官方幫助文檔:https://arthas.aliyun.com/doc/,詳細的功能和使用上面說的非常清楚,如果有實在理解不了的,加微信交流:13401182883。
1)下載
登錄被測服務(wù)器,在命令行下輸入命令:
wget?https://arthas.aliyun.com/arthas-boot.jar
2)啟動壓測
重新運行第1步的場景,開始壓測服務(wù)器。
3)啟動arthas
在命令行下面執(zhí)行(使用和目標進程一致的用戶啟動,否則可能attach失?。?/p>
java -jar arthas-boot.jar
然后選擇要監(jiān)控的進程,輸入1

4)查看dashboard
輸入dashboard,按回車,會展示當前進程的信息,按ctrl+c可以中斷執(zhí)行。

圖中出現(xiàn)了大量的紅色BLOCKED(阻塞)線程,意思是因為競爭某一個資源導(dǎo)致了線程阻塞,壓力肯定上不去呀,非常清晰。
6、定位瓶頸
通過thread命令來獲取到BLOCKED狀態(tài)的線程棧信息。
命令行輸入:thread 70

簡單解讀一下,線程棧展示的是代碼的調(diào)用鏈,執(zhí)行順序是自底向上去看。最后執(zhí)行的方法是:
com.redmoon.oa.db.SequenceManager.nextUniqueID(127行),
在這個方法中需要獲取一把鎖才可以繼續(xù)執(zhí)行,而這把鎖正在被[http-nio-8080-exec-34]這個線程鎖持有。接下來就要看34號這個線程正在做什么,為什么持有這把鎖不釋放。
命令行輸入:thread 89

發(fā)現(xiàn)這個線程持有這把鎖,沒干活卻在睡覺,接下來反編譯或者直接找開發(fā)看源碼,弄明白這個方法具體在做什么,瓶頸一目了然。發(fā)現(xiàn)瓶頸的源碼的樣子給大家看一下:

當然,這樣的瓶頸定位直接使用jstack也是完全可以做到的,只是arthas的功能更強大而已,課堂上結(jié)合更復(fù)雜的例子用的更多些。
先到這里,下篇見。
