<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      記一次.NET內存居高不下排查解決與啟示

      前情

      我們有個海外的項目,一共70個服務,前前后后花了超過一年時間完成了云服務遷移和架構調整。主要是架構調整了,原來的docker swarm托管服務,幾臺云服務器將n個服務堆在一起,只會對服務器資源做整體監控,服務器沒事沒人管單個服務的內存情況。新架構對單個服務改動不大,但外部相關架構則改頭換面了,最大的改動是容器改為Kubernetes托管,放在AWS的EKS上。新架構在新的云服務上線后,暴露了很多內存問題。在此拿某個服務根據解決過程,給個排查思路,希望能給到大家一點啟示。

      問題

      服務為一個普通的ASP.NET Core gRPC工程,平常沒什么流量。HPA設置的最大副本數為5,生產環境服務啟動后,Pod內存達到或超過K8s內存請求值(512Mi),自動觸發擴展到5個實例,即副本數達到最大。這與QA環境表現并不一樣,也就沒有在測試階段發現。需要想辦法復現、排查解決高副本和高內存占用問題。

      部署里面對容器的資源,容器資源只做了對CPU和內存的預留設置(request),沒有做上限設置(llimit)。從內存曲線上看,很多副本的內存甚至超過了請求的512Mi。不過有一點很奇怪,服務的接口并沒有出現性能下降的跡象。

       

      問題復現

      嘗試在QA環境對相關接口進行壓測,問題能復現,表現為HPA副本擴展后各個POD的內存居高不下,維持在500~600Mi長時間不釋放,有時候壓測甚至能沖到800Mi。即使沒有什么接口請求,也需要超過20個小時才緩慢下降到350Mi左右。但嘗試本地VS診斷工具則并沒有發現什么內存不釋放問題,除了一些個大對象駐留問題。

       

      代碼與dotnet-dump

      因為其他類似的服務并不會這樣,所以第一時間懷疑是代碼問題,但這么想是錯的,下面交代。懷疑代碼問題后,想著是不是有什么內存泄漏,找了個服務的接口在QA壓測后問題能復現(即內存長時間不釋放)。看了好幾遍代碼,除了一些個ToList用的太過頻繁并沒什么問題(也與內存問題不相關),用VS診斷工具檢查內存有運行又沒內存泄露問題。于是在QA環境用dotnet-dump把內存快照下載回來分析,找到了個大對象堆LOH駐留類型的類,而且VS診斷工具找到的類是同一個,接著定位到了接口調用這個類的地方。業務調用很單純,這個類就從數據庫用Dapper查出來得到列表,然后分組計算下數據,不會有什么內存泄露的機會;但注釋掉此部分查詢則內存不再上升到500~600Mi,只在300Mi左右,而且內存使用率下降也變快了。繼續二分法+注釋大法調試,最后只保留數據庫查詢語句而不做后續業務處理,連引用都不做,內存還是會達到500~600Mi。這就讓人摸不著頭腦了,代碼肯定是相關的,數據庫查詢幾下一列表數據都能讓內存達到預留臨界值(request),列表也才約11000條數據,雖然確實是LOH對象,但不至于造成這么嚴重的內存不釋放現象。

       

      GC調參

      代碼摸不著頭腦,就想辦法調試下GC。 

      方案一: 定時調用GC.Collect來回收垃圾

      加入定時執行GC.Collect()后,內存占用能立即回落,這方案似乎也可以

       

      方案二:GC配置調整:配置內存限制感知-DOTNET_GCHeapHardLimit

      添加環境變量DOTNET_GCHeapHardLimit=0x20000000 # 512Mi的十六進制值,能限制內存的使用,但并不能讓GC能敏感地進行回收,方案失敗

       

      方案三:切換為GC場景類型到工作站

      原默認為Server GC,指定為Workstation GC后,內存占用不到180Mi,擴容縮容正常,這方案看起來也可以

       

      調試結束,方案一和方案三似乎可行,查了相關資料后,兩個方案其實都有問題。方案一是代碼主動強制執行了垃圾回收,但大多數情況下并不被建議在代碼里面去執行,因為執行GC.Collect多多少少會影響服務性能,GC自己能感知內存使用率然后自動進行執行回收。至于方案三,不同的模式本來就對應著不同的服務場景,服務本身就是后端接口,切換為工作站模式也許可行,但ASP.NET Core默認就是Server GC,Server GC模式本身為了支持高性能并不會頻繁執行垃圾回收(從.NET 9開始不一樣,.NET 9的ASP.NET Core默認是第三種模式,.NET 8也支持這種模式,只不過不是默認的)。

       

      為容器限定內存上限

      查資料過程中才了解K8s的資源設置是有預留設置(request,又稱請求設置)和上限設置(limit),服務只設置了請求request部分,沒有limit部分,那有沒有可能是服務容器因為沒有被設置內存limit,導致GC如脫韁野馬般豪氣地使用內存呢?那為啥內存不釋放?就是Server GC感覺內存還是夠用的,具體文章參考:工作站和服務器垃圾回收動態適應應用程序大小 (DATAS)。先查詢下可用內存吧,于是加個下面接口查詢:

      app.MapGet("/runtime/memory", () =>
      {
          return GC.GetGCMemoryInfo().TotalAvailableMemoryBytes.ToString("N0");
      });

      結果返回:

      可用內存居然高達4Gi,真相很接近了。接著為服務設置內存limit為512Mi,再次查詢得到可用內存為512Mi。沒錯!就是少設置了內存上限,沒有這個,此時可用內存為節點內存(4GB);加了limit重新壓測,曲線:

      事件如下:

      程序內存釋放正常!副本數釋放也正常!另外接口響應時間沒有受到影響,問題得到解決!

       

      總結

      服務內存曲線高居不下是因為容器沒有被限制內存,K8s沒有指定內存limit,可用內存就是節點/宿主機的物理內存,高達4GB。沒有設置內存limit,但是設置了HPA,于是服務一啟動經過一些時間內存超過HPA閾值造成副本數增加;GC默認是Server GC,其感知的內存足夠所以不釋放(包括小對象和大對象)。雖然主動調用GC.Collect則可以釋放,但一般不會這樣做,因為GC有自己的一套邏輯。限定內存為0.5Gi后,內存釋放曲線正常,HPA擴縮正常,響應時間正常,問題得到解決,也能解釋服務的接口并沒有出現性能下降的的現象。

      啟示

      如果遇到類似內存居高不下問題,先確定.NET版本極其GC是Server GC還是Workstation GC。然后再確定其分配的可用內存是多少,K8s下要檢查其資源limit有沒有被設置。如果被設置之后依然有內存不釋放/泄露問題,再懷疑代碼問題。

       

      參考:

      為容器和 Pod 分配內存資源

      Pod 和容器的資源管理

      為 Pod 配置服務質量

      工作站和服務器垃圾回收

      內存沒有被回收

      動態適應應用程序大小 (DATAS)

      了解 Fargate Pod 配置詳細信息

       

      posted @ 2025-03-03 13:50  朝野布告  閱讀(3852)  評論(12)    收藏  舉報
      主站蜘蛛池模板: 国产精品自拍自在线播放| 麻豆国产黄色一级免费片| 亚洲色欲在线播放一区二区三区| 国产又爽又黄的精品视频| 沈阳市| 91精品蜜臀国产综合久久| 日本新janpanese乱熟| 国内精品人妻一区二区三区| 周宁县| 日韩中文字幕亚洲精品| 好深好湿好硬顶到了好爽| 亚洲欧美国产日韩天堂区| 成人午夜免费无码视频在线观看 | 最近免费中文字幕mv在线视频3| 久久精品丝袜高跟鞋| 亚洲中文字幕日产无码成人片| 欧美搡bbbbb搡bbbbb| 国产精品亚洲二区在线播放| 放荡的少妇2欧美版| 国产视频最新| 人人人澡人人肉久久精品| 久久久久久久久久久久中文字幕| 国产97视频人人做人人爱| 少妇熟女视频一区二区三区| 亚洲精品日本一区二区| 东京一本一道一二三区| 国产成人一区二区三区影院动漫| 亚洲区日韩精品中文字幕| 麻豆国产传媒精品视频| 亚洲综合一区二区三区| 国产成人精品无码专区| 亚洲高请码在线精品av| 亚洲欧美激情在线一区| 亚洲人成网线在线播放VA| 视频一区二区三区刚刚碰| 色噜噜亚洲精品中文字幕 | 欧美午夜小视频| 门国产乱子视频观看| 实拍女处破www免费看| 亚洲一区二区三区久久综合| 国产午夜在线观看视频播放|