溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么使用.NET?CPU分析某供應(yīng)鏈WEB網(wǎng)站

發(fā)布時(shí)間:2022-06-06 10:29:40 來源:億速云 閱讀:149 作者:zzz 欄目:開發(fā)技術(shù)

本篇內(nèi)容介紹了“怎么使用.NET CPU分析某供應(yīng)鏈WEB網(wǎng)站”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

    一:背景

    1. 講故事

    年前有位朋友加微信求助,說他的程序出現(xiàn)了偶發(fā)性CPU爆高,尋求如何解決,截圖如下:

    怎么使用.NET?CPU分析某供應(yīng)鏈WEB網(wǎng)站

    我建議朋友用 procdump 在 cpu 高的時(shí)候連抓兩個(gè)dump,這樣分析起來比較穩(wěn)健,朋友也如期的成功抓到,接下來就用 windbg 一起來分析下吧。

    二:Windbg 分析

    1. 查看CPU占用率

    先用 !tp 查看兩個(gè) dump 的cpu 利用率

    0:112> !tp
    CPU utilization: 100%
    Worker Thread: Total: 138 Running: 128 Idle: 10 MaxLimit: 2000 MinLimit: 400
    Work Request in Queue: 17
        Unknown Function: 00007ffe1a6617d0  Context: 000001fd9bcb20c8
        ...
    --------------------------------------
    Number of Timers: 2
    --------------------------------------
    Completion Port Thread:Total: 2 Free: 2 MaxFree: 16 CurrentLimit: 2 MaxLimit: 2000 MinLimit: 400
    0:014> !tp
    CPU utilization: 96%
    Worker Thread: Total: 173 Running: 67 Idle: 106 MaxLimit: 2000 MinLimit: 400
    Work Request in Queue: 1
        Unknown Function: 00007ffe1a6617d0  Context: 000001fda1a20be8
    --------------------------------------
    Number of Timers: 2
    --------------------------------------
    Completion Port Thread:Total: 7 Free: 7 MaxFree: 16 CurrentLimit: 7 MaxLimit: 2000 MinLimit: 400

    果然如朋友所述,接下來就可以試探的看下是不是 GC 觸發(fā)導(dǎo)致 ?

    2. 查看是否 GC 觸發(fā)

    干脆一點(diǎn)就是用 ~*e !dumpstack 導(dǎo)出所有線程的托管和非托管棧,然后搜索 GarbageCollectGeneration 就好了。

    怎么使用.NET?CPU分析某供應(yīng)鏈WEB網(wǎng)站

    果然是觸發(fā)了 GC,從調(diào)用棧信息看,當(dāng)前托管層可能正在高頻的 new 操作,導(dǎo)致只往某一個(gè)heap上狂寫數(shù)據(jù)從而致 heap 失衡,服務(wù)器模式GC為了讓多 heap 均衡,做了 heap balance 操作,接下來的線索是為什么有狂寫的情況? 還得看下托管層,使用 !clrstack 命令。

    0:112> !clrstack 
    OS Thread Id: 0x3278 (112)
            Child SP               IP Call Site
    000000b4ddc79098 00007ffe28b9fa74 [HelperMethodFrame: 000000b4ddc79098] 
    000000b4ddc791a0 00007ffda6c229cb System.Data.Entity.ModelConfiguration.Utilities.EdmPropertyPath.System.Collections.Generic.IEnumerable<System.Data.Entity.Core.Metadata.Edm.EdmProperty>.GetEnumerator()
    000000b4ddc79200 00007ffe01a179eb System.Linq.Enumerable.SequenceEqual[[System.__Canon, mscorlib]](System.Collections.Generic.IEnumerable`1<System.__Canon>, System.Collections.Generic.IEnumerable`1<System.__Canon>, System.Collections.Generic.IEqualityComparer`1<System.__Canon>)
    000000b4ddc79280 00007ffda6c2297e System.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration+c__DisplayClass14.b__11(System.Data.Entity.Core.Mapping.ColumnMappingBuilder)
    000000b4ddc792b0 00007ffe01a13f8f System.Linq.Enumerable.SingleOrDefault[[System.__Canon, mscorlib]](System.Collections.Generic.IEnumerable`1<System.__Canon>, System.Func`2<System.__Canon,Boolean>)
    000000b4ddc79330 00007ffda6c2087c System.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration.Configure(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping, System.Data.Entity.Core.Common.DbProviderManifest, System.Data.Entity.Core.Metadata.Edm.EntityType, System.Data.Entity.Core.Mapping.StorageEntityTypeMapping ByRef, Boolean, Int32, Int32)
    000000b4ddc79520 00007ffda6c20128 System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureUnconfiguredType(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping, System.Data.Entity.Core.Common.DbProviderManifest, System.Data.Entity.Core.Metadata.Edm.EntityType)
    000000b4ddc795a0 00007ffda6c1ffaf System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureTablesAndConditions(System.Data.Entity.Core.Mapping.StorageEntityTypeMapping, System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping, System.Data.Entity.Core.Common.DbProviderManifest)
    000000b4ddc79620 00007ffda6c055c0 System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntityTypes(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping, System.Data.Entity.Core.Common.DbProviderManifest)
    000000b4ddc79680 00007ffda6c05474 System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(System.Data.Entity.Core.Metadata.Edm.DbDatabaseMapping, System.Data.Entity.Core.Common.DbProviderManifest)
    000000b4ddc796d0 00007ffda69ae5c2 System.Data.Entity.DbModelBuilder.Build(System.Data.Entity.Core.Common.DbProviderManifest, System.Data.Entity.Infrastructure.DbProviderInfo)
    000000b4ddc79740 00007ffda6649ccf System.Data.Entity.DbModelBuilder.Build(System.Data.Common.DbConnection)
    000000b4ddc79780 00007ffda7b4b2d3 System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(System.Data.Entity.DbContext, System.Xml.XmlWriter)
    000000b4ddc797c0 00007ffda7b4acbe Class125.smethod_0(System.Data.Entity.DbContext)
    000000b4ddc79820 00007ffda7b4aba4 Class617.smethod_22(System.Data.Entity.DbContext)
    000000b4ddc79860 00007ffda7b4aa90 Class617.smethod_27(System.Data.Entity.DbContext)
    000000b4ddc798c0 00007ffda7b3e9ec DbContextExtensions.GetModel(System.Data.Entity.DbContext)
    000000b4ddc79910 00007ffda7b3e49b Class124.smethod_0(System.Data.Entity.DbContext, System.String)
    000000b4ddc79950 00007ffda7b3d6c3 Class486.smethod_3[[System.__Canon, mscorlib]](System.Data.Entity.DbContext, Z.BulkOperations.BulkOperation`1<System.__Canon>, System.Collections.Generic.IEnumerable`1<System.__Canon>, System.Collections.Generic.List`1<System.Object>)
    000000b4ddc79a00 00007ffda7b36871 DbContextExtensions.BulkInsert[[System.__Canon, mscorlib]](System.Data.Entity.DbContext, System.Collections.Generic.IEnumerable`1<System.__Canon>, System.Action`1<Z.EntityFramework.Extensions.EntityBulkOperation`1<System.__Canon>>)
    000000b4ddc79ab0 00007ffda7b32c65 xxx.EFRepository`1[[System.__Canon, mscorlib]].BulkInsert(System.__Canon[])
    ...

    從棧信息看,大概有如下三點(diǎn)信息:

    • 正在用 EF 做批量插入操作 BulkInsert。

    • 用了 Z.EntityFramework 插件。

    • 大量的 Build, Configure 字樣,貌似是在做什么配置,構(gòu)建啥的。

    3. 是插入數(shù)據(jù)過多導(dǎo)致的嗎?

    第一個(gè)能想到的就是 list 過大,為了驗(yàn)證,可以用 !clrstack -a 把 BulkInsert 方法的 list 參數(shù)給導(dǎo)出來。

    0:112> !clrstack -a
    OS Thread Id: 0x3278 (112)
            Child SP               IP Call Site
    000000b4ddc79b90 00007ffda7b31ee8 xxx.BLL.BaseService`1[[System.__Canon, mscorlib]].BulkInsert(System.__Canon[])
        PARAMETERS:
            this (0x000000b4ddc79d10) = 0x000001fa14bbb630
            _tArr (0x000000b4ddc79d18) = 0x000001fa14c1a2f8
    0:112> !do 0x000001fa14c1a2f8
    Name:        xxx.EntityModel.xxx[]
    MethodTable: 00007ffda9437968
    EEClass:     00007ffe02f556b0
    Size:        56(0x38) bytes
    Array:       Rank 1, Number of elements 4, Type CLASS (Print Array)
    Fields:
    None

    從輸出看,當(dāng)前的list.length=4,這就很疑惑了,既然 heap 都在 balance ,那是不是有幾個(gè)線程在猛攻? 為了驗(yàn)證就用 DbContextExtensions.BulkInsert 在所有的托管線程棧上搜關(guān)鍵詞看看。

    怎么使用.NET?CPU分析某供應(yīng)鏈WEB網(wǎng)站

    可以看到當(dāng)前有 10 處在猛攻,依次看他們的list都不大,疑惑哈????。

    4. 對(duì)問題的預(yù)判斷

    有了這些思路,但總覺得觸發(fā)GC的由頭太怪了,不過可以肯定的是問題出在了 Z.EntityFramework 插件上,按照 4S店的傳統(tǒng)經(jīng)驗(yàn),只換不修肯定沒問題,由于我對(duì) Z.EntityFramework 不熟悉,也只能這樣給到朋友了。

    說來也奇怪,朋友第二天發(fā)現(xiàn)了一個(gè)奇怪現(xiàn)象,說每次 CPU 爆高之前都出現(xiàn)了一次 w3wp的異常重啟,而重啟之后由于 Z.EntityFramework 需要預(yù)熱,導(dǎo)致后續(xù)請(qǐng)求阻塞引發(fā)的 CPU 階段性爆高。

    怎么使用.NET?CPU分析某供應(yīng)鏈WEB網(wǎng)站

    從朋友的留言加上剛才的 dump 分析,問題基本就能定位了, Build, Configure 和 banlance 操作都能解釋的通,而且還發(fā)現(xiàn)這個(gè)所謂的預(yù)熱并沒有做到串行化,而是10個(gè)線程一起來,直到預(yù)熱結(jié)束,CPU 下降。

    “怎么使用.NET CPU分析某供應(yīng)鏈WEB網(wǎng)站”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI