記一次線上服務CPU 100%的處理過程

来源:https://www.cnblogs.com/spec-dog/archive/2020/07/10/13278877.html
-Advertisement-
Play Games

告警 正在開會,突然釘釘告警聲響個不停,同時市場人員反饋客戶在投訴系統登不進了,報504錯誤。查看釘釘上的告警信息,幾台業務伺服器節點全部報CPU超過告警閾值,達100%。 趕緊從會上下來,SSH登錄伺服器,使用 top 命令查看,幾個Java進程CPU占用達到180%,190%,這幾個Java進程 ...


告警

正在開會,突然釘釘告警聲響個不停,同時市場人員反饋客戶在投訴系統登不進了,報504錯誤。查看釘釘上的告警信息,幾台業務伺服器節點全部報CPU超過告警閾值,達100%。

趕緊從會上下來,SSH登錄伺服器,使用 top 命令查看,幾個Java進程CPU占用達到180%,190%,這幾個Java進程對應同一個業務服務的幾個Pod(或容器)。

定位

  1. 使用 docker stats 命令查看本節點容器資源使用情況,對占用CPU很高的容器使用 docker exec -it <容器ID> bash 進入。

  2. 在容器內部執行 top 命令查看,定位到占用CPU高的進程ID,使用 top -Hp <進程ID> 定位到占用CPU高的線程ID。

  3. 使用 jstack <進程ID> > jstack.txt 將進程的線程棧列印輸出。

  4. 退出容器, 使用 docker cp <容器ID>:/usr/local/tomcat/jstack.txt ./ 命令將jstack文件複製到宿主機,便於查看。獲取到jstack信息後,趕緊重啟服務讓服務恢復可用。

  5. 將2中占用CPU高的線程ID使用 pringf '%x\n' <線程ID> 命令將線程ID轉換為十六進位形式。假設線程ID為133,則得到十六進位85。在jstack.txt文件中定位到 nid=0x85的位置,該位置即為占用CPU高線程的執行棧信息。如下圖所示,

jstack

  1. 與同事確認,該處為使用一個框架的excel導出功能,並且,導出excel時沒有分頁,沒有限制!!!查看SQL查詢記錄,該導出功能一次導出50w條數據,並且每條數據都需要做轉換計算,更為糟糕的是,操作者因為導出時久久沒有響應,於是連續點擊,幾分鐘內發起了10多次的導出請求。。。於是,CPU被打滿,服務崩潰了,我也崩潰了。。

解決

對於此類耗資源的操作,一定要做好相應的限制。比如可以限制請求量,控制最大分頁大小,同時可以限制訪問頻率,比如同一用戶一分鐘內最多請求多少次。

再發

服務重啟後恢復。到了下午,又一臺伺服器節點CPU告警,依前面步驟定位到占用CPU高的線程,如下

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fa114020800 nid=0x10 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fa114022000 nid=0x11 runnable 

使用命令 jstat -gcutil <進程ID> 2000 10 查看GC情況,如圖

jstat

發現Full GC次數達到1000多次,且還在不斷增長,同時Eden區,Old區已經被占滿(也可使用jmap -heap <進程ID>查看堆記憶體各區的占用情況),使用jmap將記憶體使用情況dump出來,

jmap -dump:format=b,file=./jmap.dump 13

退出容器,使用 docker cp <容器ID>:/usr/local/tomcat/jmap.dump ./ 將dump文件複製到宿主機目錄,下載到本地,使用 MemoryAnalyzer(下載地址:https://www.eclipse.org/mat/downloads.php )打開,如圖

jmap-mat

如果dump文件比較大,需要增大MemoryAnalyzer.ini配置文件中的-Xmx值

發現占用記憶體最多的是char[], String對象,通過右鍵可以查看引用對象,但點開貌似也看不出所以然來,進入記憶體泄露報告頁面,如圖

mat-leak-suspects

該頁面統計了堆記憶體的占用情況,並且給出疑似泄露點,在上圖中點開“see stacktrace”鏈接,進入線程棧頁面,

mat-thread-stack

似曾熟悉的畫面,還是跟excel導出有關,數據太多,導致記憶體溢出。。。於是GC頻繁,於是CPU爆了。根源還是同一個。

總結

本文以處理一次線上服務CPU 100%的實戰過程示例了在遇到Java服務造成伺服器CPU消耗過高或記憶體溢出的一般處理方法,希望對大家定位線上類似問題提供參考。同時,開發實現功能時需要考慮的更深遠一些,不能停留在解決當前的場景,需要考慮數據量不斷增大時,你的實現是否還能適用。俗話說,初級程式員解決當前問題,中級程式員解決兩年後的問題,高級程式員解決五年後的問題,_


[轉載請註明出處]
作者:雨歌
歡迎關註作者公眾號:半路雨歌,查看更多技術乾貨文章
qrcode


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 0. 前言 在之前的文章中簡單介紹了一下asp.net core中的Identity,這篇文章將繼續針對Identity進行進一步的展開。 1. 給Identity添加額外的信息 在《【asp.net core 系列】13 Identity 身份驗證入門》一文中,我們大概瞭解瞭如何使用Identit ...
  • Tips:本篇已加入系列文章閱讀目錄,可點擊查看更多相關文章。 前言 上一篇【.Net Core微服務入門全紀錄(七)——IdentityServer4-授權認證】中使用IdentityServer4完成了鑒權中心的搭建,配合網關實現了統一的授權認證。進行到這裡,系統環境已經比較複雜了,想把整個系統 ...
  • 封裝變化之對象創建 在對象創建的過程中,經常會出現的一個問題就是通過顯示地指定一個類來創建對象,從而導致緊耦合。這是因為創建對象時指定類名將使你受特定實現的約束而不是特定介面的約束。這會使未來的變化更加複雜。要避免這種情況,就應該間接地創建對象。 這種緊耦合的問題很大程度是由new關鍵字帶來的,由於 ...
  • 一 Nginx 連接限制 1.1 HTTP協議的連接與請求 HTTP是建立在TCP, 一次HTTP請求需要先建立TCP三次握手(稱為TCP連接),在連接的基礎上再進行HTTP請求。 HTTP請求建立在一次TCP連接基礎上,對於HTTP會話,一次TCP連接可以建立多次HTTP請求。 HTTP協議版本 ...
  • SQL自學筆記 約束 1.0概念及分類 2.0非空約束 3.0 唯一約束 4.0 主鍵約束 自動增長 5.0 外鍵約束 級聯操作 多表關係 三種情況概述 資料庫的備份和還原 多表查詢 1.0 內連接查詢 隱式內連接 : 用where條件消除無用數據 顯示內連接 : 2.0 外連接查詢 3.0 子查詢 ...
  • 先給大家看一下大佬們對這本書的評價,免得說我“標題黨” 版本控制是管理數據變更的藝術,無論數據變更是來自同一個人,還是來自不同的人(一個團隊)。版本控制系統不但要忠實地記錄數據的每一次變更, 還要能夠幫助還原任何一-次歷史變更,以及實現團隊的協同工作等。Git就是版本控制系統中的佼佼者。 當開源軟體 ...
  • 同步部分數據有兩個思路: master只發送需要的; 優點:中繼日誌小;如果多從庫,只需要在主庫中統一控制 缺點:中途修改比較麻煩,不能控制同步的表 slave只接收想要的 優點:中途修改同步的表或庫方便;可以控制需要的表和庫 缺點:中繼日誌大;如果從庫比較多,需要一個一個配置; master端 b ...
  • 前幾天HBase出現了RIT告警,忽然發現發出告警的Region所屬的表並不是我創建出來的,於是就想看看這些表是怎麼來的。 一時也沒什麼頭緒,就先看看這些表是什麼時候創建出來的吧,然後再根據時間點看看有誰操作了資料庫。 那麼怎麼看表的創建時間呢?desc看一下,也沒有這個屬性啊。再細想呢,hbase ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...