怎么排查CPU飆升
怎么排查CPU飆升
線上有些系統(tǒng),本來跑的好好的,突然有一天就會出現(xiàn)報(bào)警,CPU使用率飆升,然后重啟之后就好了。例如,多線程操作一個(gè)線程不安全的list往往就會出現(xiàn)這種現(xiàn)象。那么怎么定位到具體的代碼范圍呢?今天筆者就教大家一個(gè)小技巧
代碼準(zhǔn)備
這次,筆者準(zhǔn)備了一個(gè)demo代碼,大致線程模型是這樣的:
代碼下所示:
- public class CpuHighExample {
- public static void cpuHigh() {
- final List<String> list = new LinkedList<>();
- Thread thread1 = new Thread(new Runnable() {
- @Override
- public void run() {
- int count = 1;
- while (true) {
- // 構(gòu)造thread1為消耗很高cpu的線程
- count = count + 1;
- }
- }
- });
- thread1.setName("thread1");
- Thread thread2 = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- try {
- // 構(gòu)造thread2為消耗很低cpu的線程
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- });
- thread2.setName("thread2");
- thread1.start();
- thread2.start();
- }
- }
案例運(yùn)行
這個(gè)案例一運(yùn)行,就聽見筆者的電腦風(fēng)扇起飛了,呼呼作響。直接top一下
果然是java進(jìn)程,占用最高,CPU 100%了(占用了一個(gè)核),而其PID是2717,正是我們跑的例子。那么下一步,我們就需要定位到底是那一個(gè)線程在耗CPU
- top -H
- Threads toggle
- Starts top with the last remembered ’H’ state reversed. When this
- toggle is On, all individual threads will be displayed. Other-
- wise, top displays a summation of all threads in a process.
如man文檔所描述,top -H可以打印出線程信息,我們就top -H一下。
圖中可以看到,占用最高的線程PID是2727,同時(shí)線程名是thread1。
繼續(xù)jstack
我們知道jstack可以dump出jvm所有線程運(yùn)行的快照,然后我們就可以通過剛才獲取的PID去定位到j(luò)stack那個(gè)進(jìn)程。
- // 注意,這邊用top出來的進(jìn)程號2717,而不是top -H出來的2727
- jstack 2717 > 1.txt
由于jstack打印出的線程號是以16進(jìn)制的形式表現(xiàn)的,所以我們對2727的線程號做一次轉(zhuǎn)換,得到aa7。
然后我們在1.txt中搜索2727,這里用的是less然后進(jìn)去后搜索,而不是用grep。因?yàn)檫@樣比較直觀的能看出之前和之后的信息。less下
我們找到aa7后,就直接能發(fā)現(xiàn)代碼一直跑在CpuHighExample.java第19行上面。
當(dāng)然了,我們需要多jstack幾次,如果每次jstack出來都剛好在這段代碼左右,那么基本可以證明,是這段代碼導(dǎo)致CPU飆升了。
總結(jié)
CPU突然飆升這個(gè)問題,我們很容易通過top -H和jstack找到對應(yīng)的代碼范圍,這無疑極大的縮小了我們的定位范圍。
本文轉(zhuǎn)載自微信公眾號「 解Bug之路」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系 解Bug之路公眾號。