服務器CPU居高不下--解決問題歷程


基本的概述

在一個服務器的集群上面,服務器的CPU長時間居高不下,響應的時間也一直很慢,即使擴容了服務器CPU的下降效果也不是很明顯。

對於CPU過高的原因,可以總結到以下原因:

  • 太多的循環或者死循環

  • 加載了過多的數據,導致產生了很多的大對象

  • 產生了過多的對象,GC回收過於頻繁(如:字符串拼接)

對於上面的情況,難點不是優化代碼,難點在於定位到問題的所在,下面我們就用Dump抓包的方式來定位到問題的所在。介紹這個內容之前,我們要先回顧下.Net中垃圾回收的基礎知識和一個工具的准備。


基礎知識


垃圾回收觸發條件

  • 代碼顯示調用System.GC的靜態方法

  • windows報告低內存情況

  • CLR正在卸載AppDoamin

  • CLR正在關閉

大對象垃圾回收

CLR將對象分為大對象和小對象,認為大於85000字節或者更大的字節是大對象,CLR用不同的方式來對待大對象和小對象:

  • 大對象不是在小對象的地址空間分配,而是在進程地址空間和其他地方分配

  • GC不會壓縮大對象,在內存中移動他們的代價過高,但這樣會造成地址空間的碎片化,以至於會拋出OutOfMemeryException 異常。

  • 大對象總是在第二代回收。

工具准備

  1. 下載windbg文件

  2. 相關DLL准備clr.dll和sos.dll,(都在對應.Net版本安裝目錄下面,我的安裝目錄在C:\Windows\Microsoft.NET\Framework64\v4.0.30319)

  3. 一個cpu運行的較高的時期的DUMP文件(下面會說如何獲取)

  4. 准備測試代碼,此處為了演示方便,簡單了寫了一個有潛在問題的代碼:

public class Common { public static List<string> GetList() { var list=new List<string>(); for (int i = 0; i < 10000; i++) { list.Add(i.ToString()); } return list; } public static string GetString(List<string> list) { var str = ""; foreach (var l in list) { str += string.Format("'{0}',", l); } if (str.Length > 0) { str.Remove(str.Length - 1); } return str; } } 

我們知道在字符串的拼接的時候,每一個字符串都是一個對象,拼接后又產生了一個新對象,所以在GetString這個方法中會有大量的GC操作,下面我們就調用下這個代碼,看下CPU的情況,為了模擬並發情況,我們開多個標簽,每個標簽每1s秒中刷新一次。

CPU

抓取Dump

在任務管理器中選擇應用程序池對應的w3wp.exe,右擊–>創建轉儲文件。創建完成后,會提示出指定的路徑

taskManger

taskManger

根據上面的步驟,我們准備我們分析的文件如下:

dumpfile

分析Dump

  • 打開windbg,加載對應的dump文件

    dumpOpendumpOpen

  • 配置Sysmbol,添加”cachec:\mysymbol;srvhttp://msdl.microsoft.com/download/symbols” 
    dumpOpendumpOpen

  • load sos.dll和clr.dll,命令如下:
      .load D:\windbg\sos.dll 
      .load D:\windbg\clr.dll
    
  • 運行命令!threadpool 顯示有關托管線程池的信息,其它一些SOS 調試擴展命令.

    dumpOpen

  • 運行!runaway 查詢cpu占用時長比較長的幾個線程Id

    dumpOpen

  • 運行~22s (進入線程查看),kb(查看對應的調用)

    dumpOpen

  • 運行~* kb 查看所有線程的堆棧調用

    dumpOpen

  • 在上面搜索GC和大對象出現的線程 (ctrl+f搜索:GarbageCollectGeneration和allocate_large_object )

    dumpOpen

  • 可以看到定位觸發GC的線程是31號線程

  • 運行命令~31s 進入31線程,再運行!clrstack查看堆棧調用,最終可以定位到出問題的代碼,是由於字符串的拼接導致大量的對象產生,從而觸發了GC。

    dumpOpen


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM