日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

记一次 .NET 车联网云端服务 CPU爆高分析

發布時間:2023/12/4 asp.net 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记一次 .NET 车联网云端服务 CPU爆高分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:背景

1. 講故事

前幾天有位朋友wx求助,它的程序CPU經常飆滿,沒找到原因,希望幫忙看一下。

這些天連續接到幾個cpu爆高的dump,都看煩了????????????,希望后面再來幾個其他方面的dump,從溝通上看,這位朋友表現的好慘,可能實際更慘,那既然找到我了,我就盡最大能力幫他找到幕后真兇,話不多說,上 windbg。

二:windbg 分析

1. 查看托管線程

因為線程都是靠cpu養著,所以從線程上入手也是一個很好的思路,要想查看程序的所有托管線程,可以使用 !t 命令。

0:000>?!t ThreadCount:??????38 UnstartedThread:??0 BackgroundThread:?34 PendingThread:????0 DeadThread:???????3 Hosted?Runtime:???noLock??ID?OSID?ThreadOBJ???????????State?GC?Mode?????GC?Alloc?Context??????????????????Domain???????????Count?Apt?Exception0????1?105c?000000000067f600????2a020?Preemptive??0000000000000000:0000000000000000?0000000000671ec0?0?????MTA?2????2?13d0?00000000192c4f40????2b220?Preemptive??0000000000000000:0000000000000000?0000000000671ec0?0?????MTA?(Finalizer)? ... XXXX???15????0?000000001bc64970??8039820?Preemptive??0000000000000000:0000000000000000?0000000000671ec0?0?????MTA?(Threadpool?Completion?Port)?24???23?1380?000000001bc660e0??8029220?Preemptive??0000000000000000:0000000000000000?0000000000671ec0?0?????MTA?(Threadpool?Completion?Port)? XXXX???53????0?000000001bc63200??8039820?Preemptive??0000000000000000:0000000000000000?0000000000671ec0?0?????MTA?(Threadpool?Completion?Port)? XXXX???27?10dc?000000001bd0dbf0??1029220?Preemptive??0000000002CB40F8:0000000002CB4108?0000000000671ec0?1?????MTA?(GC)?(Threadpool?Worker)?

在卦象上看:程序有38個線程,死了3個,我去,有一個亮點,最后一行出現了一個熟悉的 MTA (GC) 字樣,這什么意思呢?這表示當前線程觸發了GC,但奇怪的是,這個觸發GC的線程死了,你肯定要問怎么看出來的,看行頭的 XXXX,先不管了,死馬當活馬醫,調出線程的所有托管和非托管棧,看看有沒有 WaitUntilGCComplete 和 try_allocate_more_space 字樣。

2. 查看線程棧

要想查看所有線程的線程棧,可以使用 ~*e !dumpstack 命令。

  • 搜索 WaitUntilGCComplete 關鍵字。

從圖中看,嘿嘿,真的有18個線程在等待,而且還看到了 System.String.Concat ,是不是和我上上篇發的 his cpu爆高是一個套路?????????????

  • 搜索 try_allocate_more_space 關鍵字。

我去,竟然沒有 try_allocate_more_space 關鍵詞,這就和 his 不是一個套路了,???????????? 有可能這個dump踩的不是特別好的時機,有可能程序正處于某些怪異行為中。

看樣子這段路走到頭了,不過還是那句話,線程是靠cpu養著的,那就硬著頭皮看看各個線程都在做什么吧,為了讓結果更清晰一點,換一個命令 ~*e !clrstack。

從圖中可以看出當前有 25 個線程正卡在 FindEntry(System.__Canon) 處,而且從調用堆棧上看,貌似是 aliyun 封裝的dll,為什么有這么多的線程卡在這里呢?這就給人一個很大的問號?接下來我就把阿里云的這段代碼給導出來看看到底發生了什么。

3. 查看問題代碼

要想導出問題代碼,還是用經典的 !ip2md + !savemodule 組合命令。

0:000>?!ip2md?000007fe9a1a0641 MethodDesc:???000007fe9a5678e0 Method?Name:??Aliyun.Acs.Core.Utils.CacheTimeHelper.AddLastClearTimePerProduct(System.String,?System.String,?System.DateTime) Class:????????000007fe9a595a08 MethodTable:??000007fe9a567900 mdToken:??????00000000060000a6 Module:???????000007fe9a561f58 IsJitted:?????yes CodeAddr:?????000007fe9a1a0610 Transparency:?Critical 0:000>?!savemodule?000007fe9a561f58?E:\dumps\AddLastClearTimePerProduct.dll 3?ps?in?file p?0?-?VA=2000,?VASize=14148,?FileAddr=200,?FileSize=14200 p?1?-?VA=18000,?VASize=3fc,?FileAddr=14400,?FileSize=400 p?2?-?VA=1a000,?VASize=c,?FileAddr=14800,?FileSize=200

然后用 ILSpy 反編譯一下這個dll,因為是阿里云的代碼,我就可以放心大膽的放出來啦。

//?Aliyun.Acs.Core.Utils.CacheTimeHelper using?System; using?System.Collections.Generic;public?class?CacheTimeHelper {private?static?Dictionary<string,?DateTime>?lastClearTimePerProduct?=?new?Dictionary<string,?DateTime>();private?const?int?ENDPOINT_CACHE_TIME?=?3600;public?static?bool?CheckCacheIsExpire(string?product,?string?regionId){string?key?=?product?+?"_"?+?regionId;DateTime?dateTime;if?(lastClearTimePerProduct.ContainsKey(key)){dateTime?=?lastClearTimePerProduct[key];}else{dateTime?=?DateTime.Now;lastClearTimePerProduct.Add(key,?dateTime);}if?(3600.0?<?(DateTime.Now?-?dateTime).TotalSeconds){return?true;}return?false;}public?static?void?AddLastClearTimePerProduct(string?product,?string?regionId,?DateTime?lastClearTime){string?key?=?product?+?"_"?+?regionId;if?(lastClearTimePerProduct.ContainsKey(key)){lastClearTimePerProduct.Remove(key);}lastClearTimePerProduct.Add(key,?lastClearTime);} }

可以看出,上面這段代碼在 if (lastClearTimePerProduct.ContainsKey(key)) 處走不下去了,如果往下追,可參考 Dictionary 的源碼。

public?class?Dictionary<TKey,?TValue>? {//?System.Collections.Generic.Dictionary<TKey,TValue>public?bool?ContainsKey(TKey?key){return?FindEntry(key)?>=?0;} }

到這里,有沒有看出這個 CacheTimeHelper 有什么問題嗎?對,竟然在多線程環境下用的是非線程安全的 Dictionary<string, DateTime>,這就很有問題了。

4. 用 Dictionary 到底會有什么問題

在多線程環境下用 Dictionary 肯定會導致數據錯亂,這個毫無疑問,而且還會遇到一些 迭代時異常,但如果說這個誤用會導致 CPU 爆高,在我的視野范圍內還沒看到過。。。為了確保起見,到 bing 上搜搜這樣的 天涯淪落人。

嘿嘿,還真的有這樣的案例:High CPU in .NET app using a static Generic.Dictionary (

https://www.tessferrandez.com/blog/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary.html

),再截個圖。

從文章描述看,簡直是一摸一樣????????????,這也就斷定在多線程環境下操作 Dictionary ,可能會導致 FindEntry(key) 時出現死循環,然后 25 個死循環一起把cpu抬起來了,補充一下當前爆滿的CPU利用率。。。

0:000>?!tp CPU?utilization:?100% Worker?Thread:?Total:?27?Running:?27?Idle:?0?MaxLimit:?32767?MinLimit:?4 Work?Request?in?Queue:?0 -------------------------------------- Number?of?Timers:?1 -------------------------------------- Completion?Port?Thread:Total:?4?Free:?3?MaxFree:?8?CurrentLimit:?3?MaxLimit:?1000?MinLimit:?4

三:總結

既然是阿里云的sdk出的bug,這問題就麻煩了。。。改也改不得,然后告訴朋友去提工單解決。

本以為事情就這樣結束了,但我想一想,幾年前用的阿里云其他 sdk 也遇到了類似CPU爆高的問題,后來通過升級sdk就搞定了,這次也賭賭看,先看一下程序集信息。

[assembly:?CompilationRelaxations(8)] [assembly:?RuntimeCompatibility(WrapNonExceptionThrows?=?true)] [assembly:?Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly:?TargetFramework(".NETStandard,Version=v2.0",?FrameworkDisplayName?=?"")] [assembly:?AssemblyCompany("Alibaba?Cloud")] [assembly:?AssemblyConfiguration("Release")] [assembly:?AssemblyCopyright("?2009-2018?Alibaba?Cloud")] [assembly:?AssemblyDescription("Alibaba?Cloud?SDK?for?C#")] [assembly:?AssemblyFileVersion("1.1.12.0")] [assembly:?AssemblyInformationalVersion("1.1.12")] [assembly:?AssemblyProduct("aliyun-net-sdk-core")] [assembly:?AssemblyTitle("aliyun-net-sdk-core")] [assembly:?AssemblyVersion("1.1.12.0")]

可以看到朋友當前用的是 1.1.12.0 版本,那就把 aliyun-net-sdk-core 升級到最新再看看這個 CacheTimeHelper 有沒有被修復 ?

果然不出所料,在新版本中給修復好了,所以經驗告訴我,用阿里云的sdk,要記得經常升級,不然各種大坑等著你。。。????????????

END

工作中的你,是否已遇到 ...?

1. CPU爆高

2. 內存暴漲

3. 資源泄漏

4. 崩潰死鎖

5. 程序呆滯

等緊急事件,全公司都指望著你能解決...? 危難時刻才能展現你的技術價值,作為專注于.NET高級調試的技術博主,歡迎微信搜索: 一線碼農聊技術,免費協助你分析Dump文件,希望我能將你的踩坑經驗分享給更多的人。

總結

以上是生活随笔為你收集整理的记一次 .NET 车联网云端服务 CPU爆高分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。