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

網(wǎng)易二面:CPU狂飆900%,該怎么處理?

數(shù)據(jù)庫 其他數(shù)據(jù)庫
并發(fā)量大并且大量SQL性能低的情況下,比如字段是沒有建立索引,則會導(dǎo)致快速CPU飆升,如果還開啟了慢日志記錄,會導(dǎo)致性能更加惡化。生產(chǎn)上有MYSQL 飆升900% 的惡劣情況。

說在前面

社群一位小伙伴面試了 網(wǎng)易,遇到了一個 性能類的面試題:

CPU飆升900%,該怎么處理?

可惜的是,以上的問題,這個小伙沒有回答理想。

最終,導(dǎo)致他網(wǎng)易之路,終止在二面,非常可惜

現(xiàn)在把這個 題目,以及參考答案,收入咱們的

《Java面試寶典 PDF》,供后面的小伙伴參考,前車之鑒啊

首先,說明一下問題:CPU飆升200% 以上是生產(chǎn)容易發(fā)生的場景

注:本文以 PDF 持續(xù)更新,最新Java 架構(gòu)筆記、面試題 的PDF文件,請后臺私信【筆記】獲取哦

場景:1:MySQL進(jìn)程飆升900%

大家在使用MySQL過程,想必都有遇到過CPU突然過高,或者達(dá)到200%以上的情況。

數(shù)據(jù)庫執(zhí)行查詢或數(shù)據(jù)修改操作時,系統(tǒng)需要消耗大量的CPU資源維護(hù)從存儲系統(tǒng)、內(nèi)存數(shù)據(jù)中的一致性。

并發(fā)量大并且大量SQL性能低的情況下,比如字段是沒有建立索引,則會導(dǎo)致快速CPU飆升,如果還開啟了慢日志記錄,會導(dǎo)致性能更加惡化。生產(chǎn)上有MYSQL 飆升900% 的惡劣情況。

場景2:Java進(jìn)程飆升900%

一般來說Java 進(jìn)程不做大量 CPU 運(yùn)算,正常情況下,CPU 應(yīng)該在 100~200% 之間,

但是,一旦高并發(fā)場景,要么走到了死循環(huán),要么就是在做大量的 GC, 容易出現(xiàn)這種 CPU 飆升的情況,CPU飆升900%,是完全有可能的。

其他場景:其他的類似進(jìn)程飆升900%的場景

比如Redis、Nginx等等。

尼恩提示:大家介紹場景的時候,就說自己主要涉及了兩個場景, Java進(jìn)程飆升900%、MySQL進(jìn)程飆升900%兩種場景,其實(shí),這兩個場景就足夠講半天了, 其他的,使用規(guī)避技巧規(guī)避一下就行。

場景一:MySQL進(jìn)程CPU飆升到900%,怎么處理?

定位過程:

  • 使用top 命令觀察,確定是mysqld導(dǎo)致還是其他原因。
  • 如果是mysqld導(dǎo)致的,show processlist,查看session情況,確定是不是有消耗資源的sql在運(yùn)行。
  • 找出消耗高的 sql,看看執(zhí)行計(jì)劃是否準(zhǔn)確, index 是否缺失,或者實(shí)在是數(shù)據(jù)量太大造成。

處理過程:

  • kill 掉這些線程(同時觀察 cpu 使用率是否下降), 一般來說,肯定要 kill 掉這些線程(同時觀察 cpu 使用率是否下降),等進(jìn)行相應(yīng)的調(diào)整(比如說加索引、改 sql、改內(nèi)存參數(shù))之后,再重新跑這些 SQL。
  • 進(jìn)行相應(yīng)的調(diào)整(比如說加索引、改 sql、改內(nèi)存參數(shù))
    index 是否缺失,如果是,則 建立索引。也有可能是每個 sql 消耗資源并不多,但是突然之間,有大量的 session 連進(jìn)來導(dǎo)致 cpu 飆升,這種情況就需要跟應(yīng)用一起來分析為何連接數(shù)會激增,再做出相應(yīng)的調(diào)整,比如說限制連接數(shù)等
  • 優(yōu)化的過程,往往不是一步完成的,而是一步一步,執(zhí)行一項(xiàng)優(yōu)化措辭,再觀察,再優(yōu)化。

場景1的真實(shí)案例:MySQL數(shù)據(jù)庫優(yōu)化的真實(shí)案例

尼恩提示:以下案例,來自互聯(lián)網(wǎng)。大家參考一下,準(zhǔn)備一個自己的案例。

本問題親身經(jīng)歷過。

之前開發(fā)同事編寫的SQL語句,就導(dǎo)致過線上CPU過高,MySQL的CPU使用率達(dá)到900%+,通過優(yōu)化最后降低到70%~80%。下面說說個人在這個過程中的排查思路。

首先,我們要對問題定位而不是盲目的開啟什么 慢日志,在并發(fā)量大并且大量SQL性能低的情況下,開啟慢日志無意是將MySQL推向崩潰的邊緣。

當(dāng)時遇到這個情況,分析了當(dāng)前的數(shù)據(jù)量、索引情況、緩存使用情況。目測數(shù)據(jù)量不大,也就幾百萬條而已。接下來就去定位索引、緩存問題。

  1. 經(jīng)過詢問,發(fā)現(xiàn)很多查詢都是走M(jìn)ySQL,沒有用到緩存。
  2. 既然沒有用到緩存,則是大量請求全部查詢MySQL導(dǎo)致。通過下面的命令查看:
show processlist;

發(fā)現(xiàn)類似很多相同的SQL語句,一直處于query狀態(tài)中。

select id form user where user_code = 'xxxxx';

初步分析可能是 user_code 字段沒有索引導(dǎo)致。接著查詢user表的索引情況:

show index form user;

發(fā)現(xiàn)這個字段是沒有建立索引。增加索引之后,該條SQL查詢能夠正常執(zhí)行。

3、沒隔一會,又發(fā)生大量的請求超時問題。接著進(jìn)行分析,發(fā)現(xiàn)是開啟了 慢日志查詢。大量的SQL查詢語句超過慢日志設(shè)置的閥值,于是將慢日志關(guān)閉之后,速度瞬間提升。CPU的使用率基本保持在300%左右。但還不是理想狀態(tài)。

4、緊接著將部分實(shí)時查詢數(shù)據(jù)的SQL語句,都通過緩存(redis)讀寫實(shí)現(xiàn)。觀察一段時間后,基本維持在了70%~80%。

總結(jié):其實(shí)本次事故的解決很簡單,就是添加索引與緩存結(jié)合使用。

  1. 不推薦在這種CPU使用過高的情況下進(jìn)行慢日志的開啟。因?yàn)榇罅康恼埱螅绻媸锹罩締栴}會發(fā)生日志磁盤寫入,性能賊低。
  2. 直接通過MySQL show processlist命令查看,基本能清晰的定位出部分查詢問題嚴(yán)重的SQL語句,在針對該SQL語句進(jìn)行分析。一般可能就是索引、鎖、查詢大量字段、大表等問題導(dǎo)致。
  3. 再則一定要使用緩存系統(tǒng),降低對MySQL的查詢頻次。
  4. 對于內(nèi)存調(diào)優(yōu),也是一種解決方案。

場景2展開:Java進(jìn)程CPU飆升到900%,怎么處理?

定位過程:

CPU飆升問題定位的一般步驟是:

  1. 首先通過top指令查看當(dāng)前占用CPU較高的進(jìn)程PID;
  2. 查看當(dāng)前進(jìn)程消耗資源的線程PID:top -Hp PID
  3. 通過print命令將線程PID轉(zhuǎn)為16進(jìn)制,根據(jù)該16進(jìn)制值去打印的堆棧日志內(nèi)查詢,查看該線程所駐留的方法位置。
  4. 通過jstack命令,查看棧信息,定位到線程對應(yīng)的具體代碼。
  5. 分析代碼解決問題。

處理過程:

  1. 如果是空循環(huán),或者空自旋。
  2. 處理方式:可以使用Thread.sleep或者加鎖,讓線程適當(dāng)?shù)淖枞?/li>
  3. 在循環(huán)的代碼邏輯中,創(chuàng)建大量的新對象導(dǎo)致頻繁GC。比如,從mysql查出了大量的數(shù)據(jù),比如100W以上等等。
  4. 處理方式:可以減少對象的創(chuàng)建數(shù)量,或者,可以考慮使用 對象池。
  5. 其他的一些造成CPU飆升的場景,比如 selector空輪訓(xùn)導(dǎo)致CPU飆升 。
  6. 處理方式:參考Netty源碼,無效的事件查詢到了一定的次數(shù),進(jìn)行 selector 重建。

Java的CPU 飆升700%優(yōu)化的真實(shí)案例

尼恩提示:以下案例,來自互聯(lián)網(wǎng)。大家參考一下,準(zhǔn)備一個自己的案例。

最近負(fù)責(zé)的一個項(xiàng)目上線,運(yùn)行一段時間后發(fā)現(xiàn)對應(yīng)的進(jìn)程竟然占用了700%的CPU,導(dǎo)致公司的物理服務(wù)器都不堪重負(fù),頻繁宕機(jī)。

那么,針對這類java進(jìn)程CPU飆升的問題,我們一般要怎么去定位解決呢?、

采用top命令定位進(jìn)程

登錄服務(wù)器,執(zhí)行top命令,查看CPU占用情況,找到進(jìn)程的pid

top

很容易發(fā)現(xiàn),PID為29706的java進(jìn)程的CPU飆升到700%多,且一直降不下來,很顯然出現(xiàn)了問題。

使用top -Hp命令定位線程

使用 top -Hp <pid> 命令(為Java進(jìn)程的id號)查看該Java進(jìn)程內(nèi)所有線程的資源占用情況(按shft+p按照cpu占用進(jìn)行排序,按shift+m按照內(nèi)存占用進(jìn)行排序)

此處按照cpu排序:

top -Hp 23602

很容易發(fā)現(xiàn),多個線程的CPU占用達(dá)到了90%多。我們挑選線程號為30309的線程繼續(xù)分析。

使用jstack命令定位代碼

1.線程號轉(zhuǎn)換5為16進(jìn)制

printf “%x\n” 命令(tid指線程的id號)將以上10進(jìn)制的線程號轉(zhuǎn)換為16進(jìn)制:

printf "%x\n"  30309

轉(zhuǎn)換后的結(jié)果分別為7665,由于導(dǎo)出的線程快照中線程的nid是16進(jìn)制的,而16進(jìn)制以0x開頭,所以對應(yīng)的16進(jìn)制的線程號nid為0x7665

2.采用jstack命令導(dǎo)出線程快照

通過使用dk自帶命令jstack獲取該java進(jìn)程的線程快照并輸入到文件中:

jstack -l 進(jìn)程ID > ./jstack_result.txt

命令(為Java進(jìn)程的id號)來獲取線程快照結(jié)果并輸入到指定文件。

jstack -l 29706 > ./jstack_result.txt

3.根據(jù)線程號定位具體代碼

在jstack_result.txt 文件中根據(jù)線程好nid搜索對應(yīng)的線程描述

cat jstack_result.txt |grep -A 100  7665

根據(jù)搜索結(jié)果,判斷應(yīng)該是ImageConverter.run()方法中的代碼出現(xiàn)問題

當(dāng)然,這里也可以直接采用

jstack <pid> |grep -A 200 <nid>

來定位具體代碼

$jstack 44529 |grep -A 200 ae24
"System Clock" #28 daemon prio=5 os_prio=0 tid=0x00007efc19e8e800 nid=0xae24 waiting on condition [0x00007efbe0d91000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrentC.TimeUnit.sleep(TimeUnit.java:386)
at com.*.order.Controller.OrderController.detail(OrderController.java:37) //業(yè)務(wù)代碼阻塞點(diǎn)

分析代碼解決問題

下面是ImageConverter.run()方法中的部分核心代碼。

邏輯說明:

/存儲minicap的socket連接返回的數(shù)據(jù)   (改用消息隊(duì)列存儲讀到的流數(shù)據(jù)) ,設(shè)置阻塞隊(duì)列長度,防止出現(xiàn)內(nèi)存溢出
//全局變量
private BlockingQueue<byte[]> dataQueue = new LinkedBlockingQueue<byte[]>(100000);
//消費(fèi)線程
@Override
public void run() {
//long start = System.currentTimeMillis();
while (isRunning) {
//分析這里從LinkedBlockingQueue
if (dataQueue.isEmpty()) {
continue;
}
byte[] buffer = device.getMinicap().dataQueue.poll();
int len = buffer.length;
}

在while循環(huán)中,不斷讀取堵塞隊(duì)列dataQueue中的數(shù)據(jù),如果數(shù)據(jù)為空,則執(zhí)行continue進(jìn)行下一次循環(huán)。

如果不為空,則通過poll()方法讀取數(shù)據(jù),做相關(guān)邏輯處理。

初看這段代碼好像每什么問題,但是如果dataQueue對象長期為空的話,這里就會一直空循環(huán),導(dǎo)致CPU飆升。

那么如果解決呢?

分析LinkedBlockingQueue阻塞隊(duì)列的API發(fā)現(xiàn):

//取出隊(duì)列中的頭部元素,如果隊(duì)列為空則調(diào)用此方法的線程被阻塞等待,直到有元素能被取出,如果等待過程被中斷則拋出InterruptedException
E take() throws InterruptedException;
//取出隊(duì)列中的頭部元素,如果隊(duì)列為空返回null
E poll();

這兩種取值的API,顯然take方法更時候這里的場景。

代碼修改為:

while (isRunning) {
/* if (device.getMinicap().dataQueue.isEmpty()) {
continue;
}*/
byte[] buffer = new byte[0];
try {
buffer = device.getMinicap().dataQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
……
}

重啟項(xiàng)目后,測試發(fā)現(xiàn)項(xiàng)目運(yùn)行穩(wěn)定,對應(yīng)項(xiàng)目進(jìn)程的CPU消耗占比不到10%。


責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2024-08-20 09:42:38

2025-03-31 08:04:50

MySQLCPU內(nèi)存

2024-10-21 00:00:01

Linux服務(wù)器CPU

2022-06-02 10:54:16

BrokerRocketMQ

2019-11-25 13:44:02

人臉識別AI人工智能

2025-03-26 00:44:00

ManagerMVC架構(gòu)

2023-03-05 22:30:25

JavaCPU

2021-01-27 05:46:56

CPU占用率命令

2021-01-28 09:28:47

CPU Linux安全

2017-11-23 10:47:47

2024-05-27 11:35:40

2022-04-15 11:26:14

緩存功能

2024-05-24 10:15:36

2018-10-23 10:28:01

服務(wù)器流量高并發(fā)

2022-09-16 08:16:25

策略模式算法

2015-07-22 17:30:14

應(yīng)用交付 太一星晨

2025-05-28 03:11:00

token鑒權(quán)session

2018-06-07 22:10:42

阿里云ET農(nóng)業(yè)大腦

2024-11-01 12:45:28

2017-02-16 19:39:29

Windows 10System進(jìn)程CPU
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 亚洲欧洲一区 | 亚洲午夜av久久乱码 | 欧美一区二区三区 | 天天插天天舔 | 日韩有码一区二区三区 | 成人一区二区电影 | 最新国产福利在线 | 精品乱子伦一区二区三区 | 欧美情趣视频 | 最新中文字幕久久 | 欧美a区| 一级毛片在线播放 | 成年免费在线观看 | 国产激情91久久精品导航 | 亚洲不卡在线视频 | 久久一区二区三区电影 | 亚洲欧美日韩系列 | 日韩五月天 | 亚洲视频二区 | av先锋资源 | 超碰在线播 | 久久久久久久久99精品 | 欧美日韩国产在线 | 我要看黄色录像一级片 | 在线观看中文字幕亚洲 | 天堂av中文在线 | 欧美久久免费观看 | 成人一区在线观看 | 国产精品美女久久久av超清 | 91精品久久久久久久久 | 成人1区2区 | 久久久91精品国产一区二区三区 | 伊人春色成人 | 日韩电影中文字幕 | 午夜精品久久久久久不卡欧美一级 | 五月婷婷在线视频 | 国产二区精品视频 | 久久久久av| 黄色一级毛片 | 狠狠干美女 | 久久免费福利 |