發(fā)布于:2021-01-14 10:08:08
0
244
0
這篇文章研究了如何解決北美主要交易應(yīng)用程序中的CPU高峰的示例。查看是什么原因?qū)е铝嗽搯栴},如何解決該問題以及您可以從中汲取哪些教訓(xùn)。
在本文中,我們將討論如何解決在北美主要交易應(yīng)用程序中出現(xiàn)的CPU高峰問題。突然,此應(yīng)用程序的CPU開始飆升至100%。
實(shí)際上,這個(gè)團(tuán)隊(duì)沒有進(jìn)行任何新的代碼部署,也沒有進(jìn)行任何環(huán)境更改,也沒有翻轉(zhuǎn)任何標(biāo)志設(shè)置-但是突然之間,CPU開始出現(xiàn)故障。
我們甚至驗(yàn)證了流量是否有所增加,這歸因于流量的激增。但是流量也沒有增加。
數(shù)據(jù)采集
該應(yīng)用程序在Java,Tomcat技術(shù)堆棧上運(yùn)行。我們要求站點(diǎn)可靠性工程(SRE)團(tuán)隊(duì)從發(fā)生此問題的機(jī)器上捕獲以下兩個(gè)工件:
1. top -H輸出
2.線程轉(zhuǎn)儲(chǔ)
讓我們看看這些工件在本節(jié)中包含什么。
1. top -H
總是由于線程導(dǎo)致CPU峰值。因此,我們必須隔離導(dǎo)致此CPU峰值的線程。顯然,此應(yīng)用程序具有數(shù)百個(gè)線程。從這數(shù)百個(gè)線程中,我們需要確定導(dǎo)致CPU消耗激增的線程?這是第一個(gè)挑戰(zhàn)。
這是“ top” unix命令行實(shí)用程序工具派上用場(chǎng)的地方。你們中的大多數(shù)人可能都熟悉“ top” unix命令行實(shí)用程序。此工具顯示設(shè)備上正在運(yùn)行的所有進(jìn)程。它還顯示了每個(gè)進(jìn)程所消耗的CPU,內(nèi)存。
該工具有一個(gè)秘密的“ -H”選項(xiàng),許多工程師對(duì)此并不熟悉??梢赃@樣調(diào)用:
$ top -H -p <PID>
PID是您的應(yīng)用程序的流程ID。顯然,此應(yīng)用程序的進(jìn)程ID為31294。因此SRE團(tuán)隊(duì)發(fā)出了此命令。
$ top -H -p 31294
當(dāng)使用“ -H”選項(xiàng)調(diào)用“ top”工具時(shí),它將開始顯示該特定進(jìn)程中正在運(yùn)行的所有線程。它還將顯示該進(jìn)程中每個(gè)線程消耗的CPU和內(nèi)存量。以下是我們從該交易應(yīng)用程序獲得的輸出:
從“ top -H”輸出中可以看到,第一行中有一個(gè)ID為“ 11956”的線程。僅此線程就消耗60.9%的CPU。答對(duì)了??!這是第一個(gè)勝利。現(xiàn)在使用此“ top -H”選項(xiàng),我們已經(jīng)確定了正在消耗大量CPU的線程。
線程轉(zhuǎn)儲(chǔ)
我們的下一個(gè)挑戰(zhàn)是識(shí)別此“ 11956”線程正在執(zhí)行的代碼行。這是線程轉(zhuǎn)儲(chǔ)很方便的地方。線程轉(zhuǎn)儲(chǔ)顯示了應(yīng)用程序中正在運(yùn)行的所有線程及其代碼執(zhí)行路徑(即堆棧跟蹤)。
重點(diǎn)介紹了捕獲線程轉(zhuǎn)儲(chǔ)的8個(gè)不同選項(xiàng)。您可以使用方便的選項(xiàng)。我們使用了JDK的“ jstack”工具來捕獲線程轉(zhuǎn)儲(chǔ)。
分析數(shù)據(jù)
現(xiàn)在,我們將“ top -H”輸出和“線程轉(zhuǎn)儲(chǔ)”都上傳到fastThread工具。如果您不確定如何將“ top -H”輸出和線程轉(zhuǎn)儲(chǔ)上傳到fastThread工具,請(qǐng)參見以下說明。
該工具能夠分析線程轉(zhuǎn)儲(chǔ)和“ top -H”輸出并生成直觀的報(bào)告。這個(gè)工具分析并生成了這個(gè)漂亮的報(bào)告。
此報(bào)告包含“ CPU | 內(nèi)存”部分。該部分將工具與top -H輸出和線程轉(zhuǎn)儲(chǔ)結(jié)合在一起,并提供應(yīng)用程序中每個(gè)線程消耗的CPU和內(nèi)存。
在上面的屏幕截圖中,我們可以看到第一行的“ WebContainer:18”線程報(bào)告正在消耗“ 60.9%” CPU。
在最后一列上,您可以看到此線程的代碼執(zhí)行路徑(即堆棧跟蹤)。您可以看到該工具現(xiàn)在報(bào)告線程名稱(即'WebContainer:18')和它正在執(zhí)行的代碼路徑(當(dāng)我們看到原始top -H輸出時(shí)不可用)。
解析度
您會(huì)注意到“ WebContainer:18”線程正在執(zhí)行java.util.WeakHashMap#put()行代碼。對(duì)于不知道的人,HashMap不是線程安全的實(shí)現(xiàn)。當(dāng)多個(gè)線程同時(shí)調(diào)用HashMap的get()和put()方法時(shí),可能會(huì)導(dǎo)致無限循環(huán)。
當(dāng)線程無限循環(huán)時(shí),CPU消耗將開始飆升。這就是此應(yīng)用程序中發(fā)生的確切問題。將WeakHashMap替換為ConcurrentHashMap后,問題已解決。
我們希望您發(fā)現(xiàn)此簡單技術(shù)有用。
作者介紹
熱門博客推薦