成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

美團(tuán)一面,你碰到過CPU 100%的情況嗎?你是怎么處理的?

開發(fā) 前端
為了防止并發(fā)場(chǎng)景中,多個(gè)線程修改公共資源,導(dǎo)致的數(shù)據(jù)異常問題,很多時(shí)候我們會(huì)在代碼中使用synchronized?或者Lock加鎖。

CPU被打滿的常見原因

1. 死循環(huán)

在實(shí)際工作中,可能每個(gè)開發(fā)都寫過死循環(huán)的代碼。

死循環(huán)有兩種:

  1. 在 while、for、forEach 循環(huán)中的死循環(huán)。
  2. 無限遞歸。

這兩種情況,程序會(huì)不停地運(yùn)行,使用寄存器保存循環(huán)次數(shù)或者遞歸深度,一直占用 cpu,導(dǎo)致 cpu 使用率飆升。

在使用 JDK1.7 時(shí),還有些死循環(huán)比如多線程的環(huán)境下,往 HashMap 中 put 數(shù)據(jù),可能會(huì)導(dǎo)致鏈表出現(xiàn)死循環(huán)。

就會(huì)導(dǎo)致cpu不斷飆高。

2.大量GC

我之前參與過餐飲相關(guān)的業(yè)務(wù)系統(tǒng)開發(fā),當(dāng)時(shí)我所在的團(tuán)隊(duì)是菜品的下游業(yè)務(wù)。

當(dāng)時(shí)菜品系統(tǒng)有菜品的更新,會(huì)發(fā)kafka消息,我們系統(tǒng)訂閱該topic,就能獲取到最近更新的菜品數(shù)據(jù)。

同步菜品數(shù)據(jù)的功能,上線了一年多的時(shí)候,沒有出現(xiàn)過什么問題。

但在某一天下午,我們收到了大量 CPU100% 的報(bào)警郵件。

追查原因之后發(fā)現(xiàn),菜品系統(tǒng)出現(xiàn)了 bug,我們每次獲取到的都是全量的菜品數(shù)據(jù),并非增量的數(shù)據(jù)。

一次性獲取的數(shù)據(jù)太多。

菜品修改還是比較頻繁的,也就是說我們系統(tǒng),會(huì)頻繁地讀取和解析大量的數(shù)據(jù),導(dǎo)致 CPU 不斷飆升。

其根本原因是頻繁的full gc。

3. 大量計(jì)算密集型任務(wù)

有時(shí)候,我們的業(yè)務(wù)系統(tǒng)需要實(shí)時(shí)計(jì)算數(shù)據(jù),比如:電商系統(tǒng)中需要實(shí)時(shí)計(jì)算優(yōu)惠后的最終價(jià)格。

或者需要在代碼中,從一堆數(shù)據(jù)中,統(tǒng)計(jì)匯總出我們所需要的數(shù)據(jù)。

如果這個(gè)實(shí)時(shí)計(jì)算或者實(shí)時(shí)統(tǒng)計(jì)的場(chǎng)景,是一個(gè)非常耗時(shí)的操作,并且該場(chǎng)景的請(qǐng)求并發(fā)量還不小,就可能會(huì)導(dǎo)致 cpu 飆高。

因?yàn)閷?shí)時(shí)計(jì)算需要消耗 cpu 資源,如果一直計(jì)算,就會(huì)一直消耗 cpu 資源。

4. 死鎖

為了防止并發(fā)場(chǎng)景中,多個(gè)線程修改公共資源,導(dǎo)致的數(shù)據(jù)異常問題,很多時(shí)候我們會(huì)在代碼中使用synchronized或者Lock加鎖。

這樣多個(gè)線程進(jìn)入臨界方法或者代碼段時(shí),需要競(jìng)爭(zhēng)某個(gè)對(duì)象或者類的鎖,只有搶到相應(yīng)的鎖,才能訪問臨界資源。其他的線程,則需要等待,擁有鎖的線程釋放鎖,下一次可以繼續(xù)競(jìng)爭(zhēng)那把鎖。

有些業(yè)務(wù)場(chǎng)景中,某段代碼需要線程獲取多把鎖,才能完成業(yè)務(wù)邏輯。

但由于代碼的 bug,或者釋放鎖的順序不正確,可能會(huì)引起死鎖的問題。

例如:

"pool-4-thread-1" prio=10 tid=0x00007f27bc11a000 nid=0x2ae9 waiting on condition [0x00007f2768ef9000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x0000000090e1d048> (a java.util.concurrent.locks.ReentrantLock$FairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)

比如線程 a 擁有鎖 c,需要獲取鎖 d,才能完成業(yè)務(wù)邏輯。

而剛好此時(shí)線程 b 擁有鎖 d,需要獲取鎖 c,才能完成業(yè)務(wù)邏輯。

線程 a 等待線程 b 釋放鎖,而線程 b 等待線程 a 釋放鎖,兩個(gè)線程都持有對(duì)方需要的鎖,無法主動(dòng)釋放,就會(huì)出現(xiàn)死鎖問題。

死鎖會(huì)導(dǎo)致 CPU 使用率飆升。

CPU被打滿如何排查

1. 使用系統(tǒng)工具和JDK自帶的jstack工具

第一步:使用top命令找出占用CPU最高的Java進(jìn)程

首先,使用top命令確認(rèn)是不是Java進(jìn)程是罪魁禍?zhǔn)住ava進(jìn)程要么是個(gè)后臺(tái)任務(wù),要么是個(gè)jar包,比如一個(gè)Spring Boot服務(wù)。

圖片圖片

假設(shè)發(fā)現(xiàn)占用CPU 99.7%的線程是Java進(jìn)程,進(jìn)程PID為13731。

第二步:找到占用CPU最高的線程

接下來,還是用top命令,只不過加一個(gè)參數(shù)-Hp,就是下面這樣:

top -Hp 13731

H參數(shù)表示要顯示線程級(jí)別的信息,p則表示指定的pid,也就是進(jìn)程ID。執(zhí)行之后,這個(gè)Java進(jìn)程中占用線程占用CPU的情況就列出來了。假設(shè)占用CPU最高的那個(gè)線程PID為13756。

圖片圖片

第三步:保存線程堆棧信息

這就要用到JDK默認(rèn)提供的一個(gè)工具——jstack。jstack用于生成Java進(jìn)程的線程快照(thread dump)。線程快照是一個(gè)關(guān)于Java進(jìn)程中所有線程當(dāng)前狀態(tài)的快照,包括每個(gè)線程的堆棧信息。通過分析線程快照,可以了解Java進(jìn)程中各個(gè)線程的運(yùn)行狀態(tài)、鎖信息等。

我們用jstack的目的是將那個(gè)占用CPU最高的線程的堆棧信息搞下來,然后進(jìn)一步分析。使用命令jstack pid > out.log將某個(gè)進(jìn)程的堆棧信息輸出到out.log文件中。

jstack 13731 > thread_stack.log

第四步:在線程棧中查找罪魁禍?zhǔn)椎木€程

將13756轉(zhuǎn)換為16進(jìn)制,可以用在線進(jìn)制轉(zhuǎn)換工具直接轉(zhuǎn)換,比如這個(gè)。轉(zhuǎn)換結(jié)果為0x35bc。

然后在線程棧中,也就是上一步保存的那個(gè)thread_stack.log文件,查找這個(gè)16進(jìn)制的線程ID(0x35bc)。

這樣,我們就能看到需要的線程名稱、線程狀態(tài),哪個(gè)方法的哪一行代碼消耗了最多的CPU都很清楚了。

圖片圖片

2. 使用Arthas探測(cè)工具

Arthas是阿里開源的一款線上監(jiān)控診斷產(chǎn)品,通過全局視角實(shí)時(shí)查看應(yīng)用load、內(nèi)存、GC、線程的狀態(tài)信息,并能在不修改應(yīng)用代碼的情況下,對(duì)業(yè)務(wù)問題進(jìn)行診斷,包括查看方法調(diào)用的入?yún)ⅰ惓#O(jiān)測(cè)方法執(zhí)行耗時(shí),類加載信息等,大大提升線上問題排查效率。

安裝Arthas

要使用Arthas,你需要先把它安裝到你的目標(biāo)服務(wù)器上。

  1. 下載jar包:
curl -O https://arthas.aliyun.com/arthas-boot.jar
  1. 啟動(dòng)Arthas服務(wù):
java -jar arthas-boot.jar

啟動(dòng)之后,會(huì)列出當(dāng)前這臺(tái)服務(wù)器上的所有Java進(jìn)程,選擇你要排查的那個(gè)服務(wù)即可。出現(xiàn)arthas@之后表示已經(jīng)啟動(dòng),并成功attach到目標(biāo)進(jìn)程上。

圖片圖片

可以輸入命令dashboard看一下實(shí)時(shí)面板,默認(rèn)5秒刷新一次,在這個(gè)面板上能夠看到線程、內(nèi)存堆棧、GC和Runtime的基本信息。如果你用過VisualVM的話,操作界面與之類似。

找到占用CPU最高的線程

執(zhí)行thread命令,這個(gè)命令會(huì)顯示所有線程的信息,并且把CPU使用率高的線程排在前面。

這樣,一眼就看出來了,第一個(gè)線程的CPU使用率高達(dá)99%。

圖片圖片

查看堆棧信息

使用thread ID獲取堆棧信息,其實(shí)就是jstack pid相同的作用。通過前一步看到這個(gè)線程的ID是18,然后執(zhí)行:

thread 18

圖片圖片

直接就看出來了出現(xiàn)問題的位置,比如TestController.java文件的high方法的第23行。然后可以進(jìn)入代碼查看具體問題。

參考答案

面試官:“你碰到過CPU 100%的情況嗎?你是怎么處理的?”

生產(chǎn)環(huán)境如果cpu已經(jīng)被打滿了,不要一上來就說什么top,jstack,記住,真實(shí)的生產(chǎn)環(huán)境如果CPU已經(jīng)要被打爆了的話

第一選擇肯定是重啟,并且如果你近段時(shí)間有發(fā)布的話,還要考慮是否可以回滾,保障生產(chǎn)環(huán)境的穩(wěn)定性是最重要的

還有就是,如果CPU已經(jīng)被打爆了,不管arthas還是jstack大概率也是執(zhí)行不了的,jvm無法響應(yīng)

我:“之前碰到過CPU被打滿的情況,我們線上第一時(shí)間做了重啟,在重啟的過程中,我們?nèi)ゲ榱朔?wù)在那段時(shí)間的日志、鏈路、指標(biāo),沒有發(fā)現(xiàn)特殊的異常。”

有時(shí)候CPU100&會(huì)伴隨非常明顯的日志、鏈路或者指標(biāo)異常。例如:通過gc的指標(biāo)發(fā)現(xiàn),發(fā)現(xiàn)full gc的次數(shù)激增,或者發(fā)現(xiàn)內(nèi)存的使用率很高,這個(gè)時(shí)候大概率是因?yàn)間c導(dǎo)致的cpu 100%。這個(gè)時(shí)候就不要再去jstack了,應(yīng)該第一次時(shí)間查看堆dump文件,確認(rèn)是哪個(gè)對(duì)象占用了大量?jī)?nèi)存

我:“當(dāng)服務(wù)重啟完成后,我們開始排查具體的原因。我們通過定期執(zhí)行top命令,發(fā)現(xiàn)java進(jìn)程的CPU的使用率確實(shí)在慢慢增加”

我:“接著,我通過top -Hp以及jstack命令拿到了應(yīng)用里cpu使用率最高的那個(gè)線程的堆棧,通過分析堆棧最終定位到了具體的代碼,是因?yàn)榇a觸發(fā)了一個(gè)臨界值,進(jìn)入了死循環(huán)”

下面這段代碼是我實(shí)際工作碰到一個(gè)導(dǎo)致線上CPU 100%的代碼:

public ShortUrlRandomSeed getAvailableSeed()  {
  MachineInfo machineInfo = UrlConverUtil.getMachineInfo();
  for (; ; ) {
    // 獲取種子
    ShortUrlRandomSeed seed = shortUrlSeedService.getAvailableSeed(machineInfo);
    if (seed != null) {
      int influenceNum = shortUrlSeedService.updateSeedStatus(seed.getId());
      if (influenceNum > 0) {
        return seed;
      }
    }
  }
}

這段代碼的作用是為了獲取一個(gè)種子用于短鏈的生成,在項(xiàng)目上線之初預(yù)生成了接近21w個(gè)種子,這個(gè)代碼在線上跑了3年了一直沒有問題,直到去年的某一天,21w個(gè)種子用光了,seed一直為null,開始死循環(huán),最終導(dǎo)致CPU 100%

責(zé)任編輯:武曉燕 來源: 明智說
相關(guān)推薦

2025-03-25 12:00:00

@Value?Spring開發(fā)

2023-02-27 09:03:23

JavaCAS

2024-04-24 09:02:58

線程池面試鎖升級(jí)

2024-04-01 00:00:00

Redis緩存服務(wù)消息隊(duì)列

2024-10-31 08:50:14

2025-04-27 01:30:01

業(yè)務(wù)系統(tǒng)QPS

2021-08-29 18:36:17

MySQL技術(shù)面試題

2023-07-13 09:16:47

循環(huán)隊(duì)列指針front?

2025-04-15 08:00:00

Java開發(fā)服務(wù)網(wǎng)格

2025-03-07 00:11:00

JWTJSONSession

2018-07-09 08:35:45

Windows 10WindowsBug

2023-04-21 13:57:38

Redis阻塞半自動(dòng)

2023-04-03 07:57:00

2024-04-22 00:00:00

CASCPU硬件

2022-06-15 09:02:32

JVM線程openJDK

2022-01-05 21:54:51

網(wǎng)絡(luò)分層系統(tǒng)

2024-04-08 00:00:00

asyncawaiPromise

2022-02-10 09:04:50

架構(gòu)

2022-11-30 17:13:05

MySQLDynamic存儲(chǔ)

2024-04-17 08:02:29

接口refused程序
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久亚洲综合 | 欧美精品综合在线 | 国产精品久久久久无码av | av男人的天堂在线 | 欧美精品网 | 国产精品久久久久久久久久久新郎 | 亚洲欧美激情精品一区二区 | 99久久99 | 欧美精品video| 99国产视频 | 亚洲久视频 | 久久av.com| 亚洲一区二区三区观看 | 一区二区av| 久色视频在线观看 | 色888www视频在线观看 | 亚洲人成一区二区三区性色 | 日韩中文字幕一区 | 美国十次成人欧美色导视频 | 第四色狠狠| 中文字幕日韩专区 | 久久看精品| 国产亚洲一区二区三区在线 | www.操com| 网站国产 | 日韩一区二区三区av | 日本视频中文字幕 | 欧美视频在线播放 | 国产乱码高清区二区三区在线 | 在线三级电影 | 国外成人免费视频 | 国产精品久久久 | 91免费看片 | 午夜小视频免费观看 | 一区二区电影网 | 日日操av| 色偷偷人人澡人人爽人人模 | 中文字幕 在线观看 | 精品国产91 | 国产成年人小视频 | 一级片aaa |