線上Spring CPU 高負(fù)載解決思路詳解
引言
背景: 在某一天,運(yùn)營同事突然發(fā)現(xiàn)運(yùn)營看板好幾天沒有更新數(shù)據(jù)了, 然后找了過來?!
這里看似拋出了一個問題 ?
但細(xì)想一下, 同時暴露了我們對于線上服務(wù)的監(jiān)控未完全覆蓋到!!! 這是致命的!!!
當(dāng)然, 這篇文章先不討論監(jiān)控的問題, 后面會推出完善的監(jiān)控方案
定位問題
問題拋過來了, 那么我們第一步要怎樣做呢?
拿到問題的第一步, 先理解題意, 這里有幾個關(guān)鍵的信息點(diǎn)
第一 : 好幾天, 具體哪一天, 這個后面確認(rèn)了一個具體的時間點(diǎn)
第二 : 運(yùn)營看板, 這是重點(diǎn), 是我們切入問題的關(guān)鍵
好了, 有了這兩個關(guān)鍵的信息, 我們接下來就開始定位問題代碼了
- 從功能出發(fā), 定位到未更新的表
- 通過表來定位到更新數(shù)據(jù)的代碼
通過上面兩步找到了問題代碼是某個定時任務(wù)
日志搜索
這時按照肌肉記憶, 先是看了代碼有沒有關(guān)鍵點(diǎn)的日志輸出, 發(fā)現(xiàn)代碼開始和結(jié)束都有打印日志的操作
順藤摸瓜,先登錄到服務(wù)器端, grep一波關(guān)鍵的日志
發(fā)現(xiàn)當(dāng)天的 info.log 沒有打印到日志, 這就很奇怪了, 因?yàn)檫@個定時任務(wù)的 cron 是每天凌晨1點(diǎn)開始
然后就查了前一天的日志, 發(fā)現(xiàn)有打印到開始的日志, 但是沒有打印結(jié)束的日志
然后再去找看有沒有異常的日志, 發(fā)現(xiàn)并沒有
監(jiān)控看板
從日志看出了一點(diǎn)不對勁的味道, 但還沒有足夠的線索定位到具體的問題
這時去查看容器的資源情況

這里觀察的是, 在兩臺容器中, 有一臺容器的 cpu 吃得很緊
另外一臺卻是風(fēng)平浪靜
從這里可以定位到大概的問題了: CPU負(fù)載高
那為什么會造成 CPU 跑那么高呢 ?
ThreadDump
當(dāng)然有很多方案可以定位 CPU 的瓶頸問題,像使用火焰圖定位(下一篇會使用到)
但從上面的蛛絲馬跡里可以大體定位到是具體的定時任務(wù)引起的
這時 threaddump, 并分析了一波線程的運(yùn)行情況

從整體的報告可以看出有阻塞的線程兩個, 同時有百分之四十是在超時等待
再看看具體被阻塞的線程

看起來是數(shù)據(jù)庫查詢阻塞
看具體的業(yè)務(wù)代碼

分析一下這條 SQL 的變量
入?yún)⒅挥幸粋€就是 classIds 數(shù)組:
- 數(shù)量很小
- 數(shù)量很大
- 數(shù)量為 0
數(shù)組的分布情況可以為上面幾種
套進(jìn)去
- 數(shù)量很小, 查詢應(yīng)該很快
- 數(shù)量很大, 查詢應(yīng)該會相對慢一點(diǎn)
- 數(shù)量為 0 呢, if 標(biāo)簽, classIds 數(shù)量為 0, 不會 拼接下面的 sql, 也就是會查全表
優(yōu)化
定位到具體的代碼了, 那就是要出優(yōu)化方案了
做法就是當(dāng) classIds 的大小為 0 的時候, 不要掃描全表

這里添加 otherwise 分支, classIds 大小為 0 是 and false
重新部署再觀察線上情況, CPU 降了下來

事后反思
為什么會這么久才發(fā)現(xiàn)問題? 而且依賴于業(yè)務(wù)側(cè)發(fā)現(xiàn)問題
能不能提前感知問題呢?
想了一下, 我們的監(jiān)控更多是在監(jiān)測代碼拋出異常, 對于操作系統(tǒng)的資源缺少監(jiān)控 下一步的優(yōu)化, 對操作系統(tǒng)資源進(jìn)行監(jiān)控
以上就是線上Spring CPU 高負(fù)載解決思路詳解的詳細(xì)內(nèi)容,更多關(guān)于線上Spring CPU 高負(fù)載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java中如何使用Gson將對象轉(zhuǎn)換為JSON字符串
這篇文章主要給大家介紹了關(guān)于Java中如何使用Gson將對象轉(zhuǎn)換為JSON字符串的相關(guān)資料,Gson是Google的一個開源項目,可以將Java對象轉(zhuǎn)換成JSON,也可能將JSON轉(zhuǎn)換成Java對象,需要的朋友可以參考下2023-11-11
Ajax 驗(yàn)證用戶輸入的驗(yàn)證碼是否與隨機(jī)生成的一致
本文主要介紹了后臺驗(yàn)證用戶輸入的驗(yàn)證碼是否與隨機(jī)生成的驗(yàn)證碼一致的方法,具有很好的參考價值,下面跟著小編一起來看下吧2017-02-02
IDEA連接MySQL數(shù)據(jù)庫的4種方法圖文教程
IDEA是一種流行的Java開發(fā)工具,可以方便地連接MySQL,這篇文章主要給大家介紹了關(guān)于IDEA連接MySQL數(shù)據(jù)庫的4種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
Java上傳文件錯誤java.lang.NoSuchMethodException的解決辦法
今天小編就為大家分享一篇關(guān)于Java上傳文件錯誤java.lang.NoSuchMethodException的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
NameNode?重啟恢復(fù)數(shù)據(jù)的流程詳解
這篇文章主要為大家介紹了NameNode?重啟恢復(fù)數(shù)據(jù)的流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
springboot配置文件中使用${}注入值的兩種方式小結(jié)
這篇文章主要介紹了springboot配置文件中使用${}注入值的兩種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03

