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