1. 程式人生 > >再一次生產 CPU 高負載排查實踐

再一次生產 CPU 高負載排查實踐

前言

前幾日早上開啟郵箱收到一封監控報警郵件:某某 ip 伺服器 CPU 負載較高,請研發儘快排查解決,傳送時間正好是凌晨。

其實早在去年我也處理過類似的問題,並記錄下來:《一次生產 CPU 100% 排查優化實踐》

不過本次問題產生的原因卻和上次不太一樣,大家可以接著往下看。

問題分析

收到郵件後我馬上登陸那臺伺服器,看了下案發現場還在(負載依然很高)。

於是我便利用這類問題的排查套路定位一遍。


首先利用 top -c 將系統資源使用情況實時顯示出來 (-c 引數可以完整顯示命令)。

接著輸入大寫 P 將應用按照 CPU 使用率排序,第一個就是使用率最高的程式。

果不其然就是我們的一個 Java

應用。

這個應用簡單來說就是定時跑一些報表使的,每天凌晨會觸發任務排程,正常情況下幾個小時就會執行完畢。


常規操作第二步自然是得知道這個應用中最耗 CPU 的執行緒到底再幹嘛。

利用 top -Hp pid 然後輸入 P 依然可以按照 CPU 使用率將執行緒排序。

這時我們只需要記住執行緒的 ID 將其轉換為 16 進位制儲存起來,通過 jstack pid >pid.log 生成日誌檔案,利用剛才儲存的 16 進位制程序 ID 去這個執行緒快照中搜索即可知道消耗 CPU 的執行緒在幹啥了。

如果你嫌麻煩,我也強烈推薦阿里開源的問題定位神器 arthas 來定位問題。

比如上述操作便可精簡為一個命令 thread -n 3

即可將最忙碌的三個執行緒快照打印出來,非常高效。

更多關於 arthas 使用教程請參考官方文件

由於之前忘記截圖了,這裡我直接得出結論吧:

最忙綠的執行緒是一個 GC 執行緒,也就意味著它在忙著做垃圾回收。

GC 檢視

排查到這裡,有經驗的老司機一定會想到:多半是應用記憶體使用有問題導致的。

於是我通過 jstat -gcutil pid 200 50 將記憶體使用、gc 回收狀況打印出來(每隔 200ms 列印 50次)。

從圖中可以得到以下幾個資訊:

  • Eden 區和 old 區都快佔滿了,可見記憶體回收是有問題的。
  • fgc 回收頻次很高,10s 之內發生了 8 次回收((866493-866485)/ (200 *5)
    )。
  • 持續的時間較長,fgc 已經發生了 8W 多次。

記憶體分析

既然是初步定位是記憶體問題,所以還是得拿一份記憶體快照分析才能最終定位到問題。

通過命令 jmap -dump:live,format=b,file=dump.hprof pid 可以匯出一份快照檔案。

這時就得藉助 MAT 這類的分析工具出馬了。

問題定位

通過這張圖其實很明顯可以看出,在記憶體中存在一個非常大的字串,而這個字串正好是被這個定時任務的執行緒引用著。

大概算了一下這個字串所佔的記憶體為 258m 左右,就一個字串來說已經是非常大的物件了。

那這個字串是咋產生的呢?

其實看上圖中的引用關係及字串的內容不難看出這是一個 insertSQL 語句。

這時不得不讚嘆 MAT 這個工具,他還能幫你預測出這個記憶體快照可能出現問題地方同時給出執行緒快照。

最終通過這個執行緒快照找到了具體的業務程式碼:

他呼叫一個寫入資料庫的方法,而這個方法會拼接一個 insert 語句,其中的 values 是迴圈拼接生成,大概如下:

    <insert id="insert" parameterType="java.util.List">
        insert into xx (files)
        values
        <foreach collection="list" item="item" separator=",">
            xxx
        </foreach>
    </insert>

所以一旦這個 list 非常大時,這個拼接的 SQL 語句也會很長。

通過剛才的記憶體分析其實可以看出這個 List 也是非常大的,也就導致了最終的這個 insert 語句佔用的記憶體巨大。

優化策略

既然找到問題原因那就好解決了,有兩個方向:

  • 控制源頭 List 的大小,這個 List 也是從某張表中獲取的資料,可以分頁獲取;這樣後續的 insert 語句就會減小。
  • 控制批量寫入資料的大小,其實本質還是要把這個拼接的 SQL 長度降下來。
  • 整個的寫入效率需要重新評估。

總結

本次問題從分析到解決花的時間並不長,也還比較典型,其中的過程再總結一下:

  • 首先定位消耗 CPU 程序。
  • 再定位消耗 CPU 的具體執行緒。
  • 記憶體問題 dump 出快照進行分析。
  • 得出結論,調整程式碼,測試結果。

最後願大家都別接到生產告警。

你的點贊與分享是對我最大的支援

相關推薦

生產 CPU 負載排查實踐

前言 前幾日早上開啟郵箱收到一封監控報警郵件:某某 ip 伺服器 CPU 負載較高,請研發儘快排查解決,傳送時間正好是凌晨。 其

linux程序和執行緒排查 · 記JVM CPU負載排查辦法

前言通過本文,你將學會:1、linux上程序及程序中執行緒排查的基本方法,如檢視程序中的執行緒數此文中的執行緒一般指輕量級程序。檢視所有程序資訊 top -H 加上-H這個選項啟動top,top一行顯示一個執行緒(指的是(輕量級)程序? )。否則,它一行顯示一個程序。先輸入

線上CPU的問題排查實踐

一次線上CPU高的問題排查實踐 前言 近期某一天上班一開電腦,就收到了運維警報,有兩臺服務CPU負載很高,同時收到一線同事反饋 系統訪問速度非常慢,幾乎無響應。 一個美好的早晨,最怕什麼就來什麼。只好推掉其他會議,專心搞定問題。 排查 登入系統一看,後端的介面訪問果然全部超時。 先使用top命令檢視下是由哪

生產環境記憶體故障排查

最近生產環境經常有個伺服器出現記憶體報警,上面跑了個java介面服務,但大概一段時間後會自動恢復。報警如下圖: 由於故障已自動恢

TPS低,CPU--記storm壓測問題排查過程

進入 狀態 其他 value 由於 均衡 線程狀態 左右 grep 命令 一、業務背景+系統架構 本次場景為kafka+storm+redis+hbase,通過kafka的數據,進入storm的spout組件接收,轉由storm的Bolt節點進行業務邏輯處

生產環境CPU佔用飆問題解決

1 問題來源與背景 問題背景,專案對外提供查詢航班艙位介面,對航信黑屏報文做正則解析返回。由於起初對正則不熟悉,對黑屏報文格式規律不清楚,導致寫了大量的長正則表示式,生產環境併發量上來(200/s),直

線上機器load負載報警問題排查及其後續處理

問題來源:從3.14號開始陸續收到線上一臺機器的負載過高報警 問題排查 : 於是對gc、堆記憶體、load負載、cpu使用情況等進行了統計分析。 gc時間圖示 堆記憶體使用情況: load負載 cpu使用率 通過以上對gc的統計,

CDN源站負載的問題排查及解決

https hit 兩個 ext 繼續 都是 cto 但是 指定節點 最近總是收到後端的CDN源站的負載高的報警,Apache經常會觸發重啟。於是啟動排查問題。 我們的CDN架構如下: 我們的CDN緩存策略是:使用源站的緩存策略,源站緩存策略是365天。 首先查看Apach

CPU負載異常排查實踐與總結

昨天下午突然收到運維郵件報警,顯示資料平臺伺服器cpu利用率達到了98.94%,而且最近一段時間一直持續在70%以上,看起來像是硬體資源到瓶頸需要擴容了,但仔細思考就會發現咱們的業務系統並不是一個高併發或者CPU密集型的應用,這個利用率有點太誇張,硬體瓶頸應該不會這麼快就到了,一定是哪裡的業務程式碼邏輯有問題

(轉載)生產系統 Full GC 問題分析與排查總結

一次生產系統 Full GC 問題分析與排查總結   轉載請註明 AIQ - 最專業的機器學習大資料社群  http://www.6aiq.com AIQ 機器學習大資料 知乎專欄 點選關注 一次生產系統 Full GC 問題分

MySQL案例:單核CPU佔用過問題的處理

客戶現場反饋,top的檢查結果中,一個CPU的佔用一直是100%。實際上現場有4個CPU,而且這個伺服器是mysql專屬伺服器。 我的第一反應是io_thread一類的引數設定有問題,檢查以後發現read和write的thread設定都是4,這和CPU數一致,因此可以斷定這並不是單顆CPU佔用過高的問題。

生產DB2資料庫鎖超時問題的分析與排查

作者介紹 侯君,證通股份有限公司DBA,主要負責DB2、MySQL、Couchbase運維,以及自動化運維平臺開發,Python愛好者。 前言 DB2的鎖管理機制一直為DB2應用開發人員和DBA所詬病。對其鎖機制不理解的直接後果就是導致鎖超時和死鎖的發生。所以監控並分析鎖超時和死鎖,應是每個DB2

JVM效能分析 | 生產系統Full GC問題分析與排查總結

一次生產系統Full GC問題分析與排查總結 背景 最近某線上業務系統生產環境頻頻CPU使用率過低,頻繁告警,通過重啟可以緩解,但是過了一段時間又會繼續預警,線上兩個服務節點相繼出現CPU資源緊張,導致伺服器卡死不可用,通過告警資訊可以看到以下問題:

Unite'17 Shanghai問候

經理 動畫 nal 會議 公司 遊戲開發 一場 未來 family Unite‘17 Shanghai再一次問候 --暨Unity2017年度大會 2017年5月11日,主題為“再一次問候”的Unity年度盛會在上海國際會議中心舉行,這是Unity繼GDC

記錄concurrent mode failure問題排查過程以及解決思路

tails only cnblogs 策略 executor red execute incr run 背景:後臺定時任務腳本每天淩晨5點30會執行一個批量掃庫做業務的邏輯。 gc錯誤日誌: 2017-07-05T05:30:54.408+0800: 518534

JVM Metaspace溢出排查

jvm參數 oom task visualvm map 排除 創建 thread 類裝載 多圖預警! 環境:系統測試(Windows Server/JRE8/tomcat7) 現象:應用運行幾天後,出現訪問超時,服務器cpu利用率居高不下 問題日誌:OutOfMemory

動態規劃和分治法,貪心算法以及遞歸的深刻理解和體會

規劃 動態 分治法 每次體會算法都有新的感覺,刷題越多,對算法的理解感覺也就越深刻。下面我們來重新體會下分治法,動態規劃,貪心法,遞歸的理解。1.分治法: 將問題分成單獨的階段,每個階段互相不幹擾很獨立,如10米長的木棍,切成10段,每段去解決每一段的問題。(階段沒有關系)2.貪心法 站

生產的bug

{} 測試 led 過程 生產 日期 代碼上線 返回 隱藏   第一個在代碼中使用 new SimpleDateFormat("EEEE")來判斷周幾。在本地測試過程中通過日誌打印出來的周幾 比如周日對應的是中文漢字“星期日”,然後使用判斷 if("星期日".equals(

database cpu high的處理

業務 read 需要 十分 時有 一次 -1 技術 ima 基本上,我們的數據庫實例每次cpu飆升都是因read而起,很少有write導致的cpu高。這說明read,隨機讀,排序,都會占用cpu。而寫入主要是io行為,尤其是順序寫,不需要占cpu。 今次問題,rds在三個小

生產環境下MongoDB備份還原數據

刪除 命令格式 type 庫存 功能 字符 導出文件 信息 fields 最近開發一個版本的功能當中用到了MongoDB分頁,懶於造數據,於是就研究了下從生產環境上導出數據到本地來進行測試。 研究了一下,發現MongoDB的備份還原和MySQL語法還挺類似,下面請看詳細介紹