線上CPU 100%故障應(yīng)急處理實(shí)戰(zhàn):3分鐘內(nèi)快速定位問(wèn)題的終極指南
真實(shí)案例背景:凌晨2點(diǎn),監(jiān)控告警瘋狂響起,電商網(wǎng)站訪問(wèn)緩慢,用戶投訴激增。服務(wù)器CPU使用率飆升至100%,你有3分鐘時(shí)間找到問(wèn)題根源,否則將面臨巨大的業(yè)務(wù)損失...
作為一名有著8年運(yùn)維經(jīng)驗(yàn)的老司機(jī),我經(jīng)歷過(guò)無(wú)數(shù)次深夜被電話叫醒的"驚喜"。今天分享一次典型的CPU 100%故障處理全過(guò)程,希望能幫你在關(guān)鍵時(shí)刻快速定位問(wèn)題。
故障現(xiàn)象:用戶體驗(yàn)急劇下降
時(shí)間線回顧:
? 02:15 - 監(jiān)控告警:服務(wù)器CPU使用率持續(xù)超過(guò)95%
? 02:16 - 用戶反饋:頁(yè)面加載超過(guò)10秒
? 02:17 - 運(yùn)營(yíng)通知:訂單量斷崖式下跌
? 02:18 - 開始緊急排查...
關(guān)鍵指標(biāo)異常:
# 系統(tǒng)負(fù)載異常高 load average: 8.5, 7.2, 6.8 # 正常應(yīng)該在2以下 # CPU使用率 %Cpu(s): 98.2 us, 1.2 sy, 0.0 ni, 0.6id # 內(nèi)存使用正常 KiB Mem : 16GB total, 2GB free
第一步:快速定位CPU消耗大戶(30秒內(nèi))
使用top命令進(jìn)行初步排查
# 按CPU使用率排序,實(shí)時(shí)刷新 top -o %CPU # 輸出示例 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12847 www 20 0 2.2g 1.8g 12m R 89.5 11.2 145:32 java 8934 mysql 20 0 1.6g 800m 32m S 8.2 5.1 23:45 mysqld 3421 nginx 20 0 128m 45m 8m S 1.2 0.3 2:34 nginx
關(guān)鍵發(fā)現(xiàn):Java進(jìn)程(PID 12847)占用89.5%的CPU!
深入分析Java進(jìn)程內(nèi)部線程
# 查看Java進(jìn)程內(nèi)部線程CPU使用情況 top -H -p 12847 # 輸出關(guān)鍵信息 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12851 www 20 0 2.2g 1.8g 12m R 45.2 11.2 89:23 java 12856 www 20 0 2.2g 1.8g 12m R 44.3 11.2 78:45 java 12863 www 20 0 2.2g 1.8g 12m S 2.1 11.2 5:34 java
重要線索:兩個(gè)線程(12851、12856)消耗了近90%的CPU資源!
第二步:精確定位問(wèn)題代碼(2分鐘內(nèi))
獲取Java線程堆棧信息
# 將線程ID轉(zhuǎn)換為16進(jìn)制(Java堆棧中使用16進(jìn)制) printf"0x%x "12851 # 輸出:0x3233 printf"0x%x "12856 # 輸出:0x3238 # 獲取Java進(jìn)程完整堆棧 jstack 12847 > /tmp/java_stack.txt # 在堆棧中查找對(duì)應(yīng)線程 grep -A 20"0x3233"/tmp/java_stack.txt
堆棧分析結(jié)果
"pool-2-thread-1"#23prio=5os_prio=0tid=0x... nid=0x3233runnable
java.lang.Thread.State: RUNNABLE
at com.company.service.OrderService.calculateDiscount(OrderService.java:245)
at com.company.service.OrderService.processOrder(OrderService.java:189)
at com.company.controller.OrderController.submitOrder(OrderController.java:67)
- locked <0x000000076ab62208> (a java.lang.Object)
"pool-2-thread-2"#24prio=5os_prio=0tid=0x... nid=0x3238runnable
java.lang.Thread.State: RUNNABLE
at com.company.service.OrderService.calculateDiscount(OrderService.java:245)
- waiting to lock <0x000000076ab62208> (a java.lang.Object)
關(guān)鍵發(fā)現(xiàn):
1. 問(wèn)題定位到OrderService.calculateDiscount方法的245行
2. 存在鎖競(jìng)爭(zhēng)問(wèn)題,多個(gè)線程在爭(zhēng)奪同一個(gè)鎖資源
3. 線程狀態(tài)顯示為RUNNABLE但實(shí)際在等待鎖
第三步:代碼層面問(wèn)題分析
查看問(wèn)題代碼
// OrderService.java 第245行附近
publicsynchronizedBigDecimalcalculateDiscount(Order order){
// 問(wèn)題代碼:在同步方法中執(zhí)行了耗時(shí)的外部API調(diào)用
try{
// 調(diào)用第三方優(yōu)惠券驗(yàn)證API - 耗時(shí)3-5秒
CouponValidationResultresult=thirdPartyApi.validateCoupon(order.getCouponCode());
// 復(fù)雜的折扣計(jì)算邏輯
for(inti=0; i 1000000; i++) { ?// 模擬復(fù)雜計(jì)算
? ? ? ? ? ??// 大量計(jì)算操作
? ? ? ? }
? ? ? ??
? ? ? ??return?calculateFinalDiscount(result, order);
? ? }?catch?(Exception e) {
? ? ? ? log.error("折扣計(jì)算失敗", e);
? ? ? ??return?BigDecimal.ZERO;
? ? }
}
問(wèn)題根因分析:
1.鎖粒度過(guò)大:整個(gè)方法使用synchronized,導(dǎo)致所有折扣計(jì)算串行執(zhí)行
2.耗時(shí)操作在鎖內(nèi):第三方API調(diào)用在鎖保護(hù)范圍內(nèi),嚴(yán)重影響并發(fā)性能
3.復(fù)雜計(jì)算邏輯:大量循環(huán)計(jì)算進(jìn)一步加劇了鎖競(jìng)爭(zhēng)
第四步:緊急處理方案(1分鐘內(nèi)執(zhí)行)
臨時(shí)解決方案:限流 + 緩存
# 1. 緊急重啟應(yīng)用(如果可接受短暫中斷) systemctl restart your-app # 2. 開啟Nginx限流(降低并發(fā)壓力) # /etc/nginx/conf.d/rate-limit.conf limit_req_zone$binary_remote_addrzone=order:10m rate=10r/s; location /api/order { limit_req zone=order burst=20 nodelay; proxy_pass http://backend; } # 重載Nginx配置 nginx -s reload # 3. 臨時(shí)禁用優(yōu)惠券功能(業(yè)務(wù)降級(jí)) # 在配置中心快速切換feature flag curl -X PUT http://config-center/api/features/coupon-validation -d'{"enabled": false}'
第五步:根本性修復(fù)方案
代碼重構(gòu):異步化 + 細(xì)粒度鎖
@Service
publicclassOrderService{
privatefinalRedisTemplate redisTemplate;
privatefinalCouponValidationService couponService;
// 移除synchronized,改為細(xì)粒度鎖控制
publicCompletableFuturecalculateDiscountAsync(Order order){
returnCompletableFuture.supplyAsync(() -> {
StringlockKey="discount_calc_"+ order.getUserId();
// 使用Redis分布式鎖,避免單機(jī)鎖競(jìng)爭(zhēng)
returnredisTemplate.execute(newRedisCallback() {
@Override
publicBigDecimaldoInRedis(RedisConnection connection){
try{
// 嘗試獲取鎖,超時(shí)時(shí)間1秒
BooleanlockAcquired=connection.setNX(
lockKey.getBytes(),"1".getBytes()
);
connection.expire(lockKey.getBytes(),5);// 5秒過(guò)期
if(lockAcquired) {
returndoCalculateDiscount(order);
}else{
// 獲取鎖失敗,返回默認(rèn)折扣
returngetDefaultDiscount(order);
}
}finally{
connection.del(lockKey.getBytes());
}
}
});
});
}
privateBigDecimaldoCalculateDiscount(Order order){
// 1. 先檢查緩存
StringcacheKey="discount_"+ order.getCouponCode();
BigDecimalcachedDiscount=(BigDecimal) redisTemplate.opsForValue().get(cacheKey);
if(cachedDiscount !=null) {
returncachedDiscount;
}
// 2. 異步調(diào)用第三方API,設(shè)置超時(shí)時(shí)間
CompletableFuture apiCall =
couponService.validateCouponAsync(order.getCouponCode())
.orTimeout(2, TimeUnit.SECONDS) // 2秒超時(shí)
.exceptionally(ex -> {
log.warn("優(yōu)惠券驗(yàn)證超時(shí),使用默認(rèn)策略", ex);
returnCouponValidationResult.defaultResult();
});
try{
CouponValidationResultresult=apiCall.get();
BigDecimaldiscount=calculateFinalDiscount(result, order);
// 3. 緩存結(jié)果,避免重復(fù)計(jì)算
redisTemplate.opsForValue().set(cacheKey, discount, Duration.ofMinutes(10));
returndiscount;
}catch(Exception e) {
log.error("折扣計(jì)算異常", e);
returngetDefaultDiscount(order);
}
}
}
性能監(jiān)控改進(jìn)
// 添加方法級(jí)別的性能監(jiān)控
@Around("@annotation(Timed)")
publicObjectlogExecutionTime(ProceedingJoinPoint joinPoint)throwsThrowable {
longstart=System.currentTimeMillis();
Objectproceed=joinPoint.proceed();
longexecutionTime=System.currentTimeMillis() - start;
// 超過(guò)1秒的方法記錄告警
if(executionTime >1000) {
log.warn("方法執(zhí)行時(shí)間過(guò)長(zhǎng): {} ms, 方法: {}",
executionTime, joinPoint.getSignature());
}
returnproceed;
}
第六步:效果驗(yàn)證與長(zhǎng)期監(jiān)控
修復(fù)前后對(duì)比
| 指標(biāo) | 修復(fù)前 | 修復(fù)后 | 改善幅度 |
|---|---|---|---|
| CPU使用率 | 98% | 25% | ↓ 73% |
| 響應(yīng)時(shí)間 | 8-12秒 | 200-500ms | ↓ 95% |
| 并發(fā)處理能力 | 10 TPS | 200 TPS | ↑ 1900% |
| 系統(tǒng)負(fù)載 | 8.5 | 1.2 | ↓ 86% |
建立預(yù)警機(jī)制
# Prometheus告警規(guī)則
groups:
- name: cpu_alerts
rules:
- alert: HighCPUUsage
expr: cpu_usage_percent > 80
for: 2m
annotations:
summary:"服務(wù)器CPU使用率過(guò)高"
description:"CPU使用率已達(dá)到{{$value}}%,持續(xù)超過(guò)2分鐘"
- alert: JavaThreadBlocked
expr: jvm_threads_blocked_count > 10
for: 1m
annotations:
summary:"Java線程阻塞數(shù)量異常"
description:"阻塞線程數(shù)量:{{$value}}"
業(yè)務(wù)影響與價(jià)值總結(jié)
直接收益
?故障處理時(shí)間:從平均30分鐘縮短到3分鐘
?用戶體驗(yàn)提升:頁(yè)面響應(yīng)時(shí)間從10秒降至0.5秒
?業(yè)務(wù)損失避免:預(yù)估避免每小時(shí)50萬(wàn)元的訂單損失
技術(shù)債務(wù)清理
? 重構(gòu)了23個(gè)類似的同步方法
? 建立了完整的性能監(jiān)控體系
? 制定了代碼review檢查清單
經(jīng)驗(yàn)總結(jié):運(yùn)維老司機(jī)的5個(gè)黃金法則
1. 建立分層監(jiān)控體系
# 系統(tǒng)層監(jiān)控 - CPU/Memory/Disk/Network基礎(chǔ)指標(biāo) - Load Average和進(jìn)程狀態(tài) # 應(yīng)用層監(jiān)控 - JVM堆內(nèi)存、GC狀況、線程狀態(tài) - 接口響應(yīng)時(shí)間、錯(cuò)誤率、TPS # 業(yè)務(wù)層監(jiān)控 - 關(guān)鍵業(yè)務(wù)指標(biāo)實(shí)時(shí)追蹤 - 用戶行為數(shù)據(jù)異常檢測(cè)
2. 掌握快速定位工具鏈
# CPU問(wèn)題定位三板斧 top → jstack → 代碼分析 # 常用命令組合 ps aux | grep java # 找到Java進(jìn)程 top -H -p# 查看進(jìn)程內(nèi)線程 jstack | grep -A 10 # 分析線程堆棧
3. 制定標(biāo)準(zhǔn)化應(yīng)急預(yù)案
?2分鐘:?jiǎn)栴}確認(rèn)和初步定位
?5分鐘:實(shí)施臨時(shí)解決方案
?30分鐘:根因分析和永久修復(fù)
?1小時(shí):復(fù)盤總結(jié)和預(yù)防措施
4. 重視代碼性能review
?鎖使用原則:鎖粒度最小化,鎖持有時(shí)間最短化
?異步化改造:耗時(shí)操作必須異步化處理
?緩存策略:合理使用多級(jí)緩存避免重復(fù)計(jì)算
5. 建立知識(shí)庫(kù)和工具箱
每次故障處理后都要沉淀:
?故障案例庫(kù):典型問(wèn)題的診斷和解決步驟
?腳本工具箱:自動(dòng)化診斷和修復(fù)腳本
?監(jiān)控儀表板:可視化的系統(tǒng)健康狀態(tài)
寫在最后
作為運(yùn)維工程師,我們就是系統(tǒng)的"醫(yī)生"。面對(duì)CPU 100%這樣的"急癥",需要的不僅是技術(shù)能力,更重要的是冷靜的分析思路和系統(tǒng)性的解決方案。
-
cpu
+關(guān)注
關(guān)注
68文章
11277瀏覽量
224942 -
服務(wù)器
+關(guān)注
關(guān)注
14文章
10251瀏覽量
91480
原文標(biāo)題:線上CPU 100%故障應(yīng)急處理實(shí)戰(zhàn):3分鐘內(nèi)快速定位問(wèn)題的終極指南
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
CPU常見故障的處理
eps應(yīng)急電源常見故障和維修
【修復(fù)】消防應(yīng)急燈故障檢測(cè)及修復(fù)
EJA智能雙法蘭差壓變送器的典型故障處理
設(shè)備故障應(yīng)急處理的方法與技巧
主動(dòng)數(shù)據(jù)庫(kù)在聯(lián)鎖故障應(yīng)急處理中的應(yīng)用
筆記本啟動(dòng)故障修復(fù)實(shí)戰(zhàn)
視頻系統(tǒng)的故障排除和應(yīng)急處理
KGPS型可控硅中頻電源典型故障處理
典型CPU故障應(yīng)急處理實(shí)戰(zhàn)
評(píng)論