中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現線上JVM調優

發布時間:2021-10-25 15:19:44 來源:億速云 閱讀:318 作者:iii 欄目:編程語言

本篇內容主要講解“如何實現線上JVM調優”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何實現線上JVM調優”吧!

YGC耗時過長的排查與解決案例

我們的廣告服務在新版本上線后,收到了大量的服務超時告警,通過下面的監控圖可以看到:超時量突然大面積增加,1分鐘內甚至達到了上千次接口超時。下面詳細介紹下該問題的排查過程。

如何實現線上JVM調優

1.檢查監控

收到告警后,我們第一時間查看了監控系統,立馬發現了YoungGC耗時過長的異常。我們的程序大概在21點50左右上線,通過下圖可以看出:在上線之前,YGC基本幾十毫秒內完成,而上線后YGC耗時明顯變長,最長甚至達到了3秒多。

如何實現線上JVM調優

由于YGC期間程序會Stop The World,而我們上游系統設置的服務超時時間都在幾百毫秒,因此推斷:是因為YGC耗時過長引發了服務大面積超時。
按照GC問題的常規排查流程,我們立刻摘掉了一個節點,然后通過以下命令dump了堆內存文件用來保留現場。
jmap -dump:format=b,file=heap pid
最后對線上服務做了回滾處理,回滾后服務立馬恢復了正常,接下來就是長達1天的問題排查和修復過程。

2.確認JVM配置

用下面的命令,我們再次檢查了JVM的參數

如何實現線上JVM調優

可以看到堆內存為4G,新生代和老年代均為2G,新生代采用ParNew收集器。
再通過命令 jmap -heap pid 查到:新生代的Eden區為1.6G,S0和S1區均為0.2G。
本次上線并未修改JVM相關的任何參數,同時我們服務的請求量基本和往常持平。因此猜測:此問題大概率和上線的代碼相關。

3.代碼檢查

再回到YGC的原理來思考這個問題,一次YGC的過程主要包括以下兩個步驟:

  • 從GC Root掃描對象,對存活對象進行標注

  • 將存活對象復制到S1區或者晉升到Old區

根據下面的監控圖可以看出:正常情況下,Survivor區的使用率一直維持在很低的水平(大概30M左右),但是上線后,Survivor區的使用率開始波動,最多的時候快占滿0.2G了。而且,YGC耗時和Survivor區的使用率基本成正相關。因此,我們推測:應該是長生命周期的對象越來越多,導致標注和復制過程的耗時增加。

如何實現線上JVM調優

再回到服務的整體表現:上游流量并沒有出現明顯變化,正常情況下,核心接口的響應時間也基本在200ms以內,YGC的頻率大概每8秒進行1次。

很顯然,對于局部變量來說,在每次YGC后就能夠馬上被回收了。那為什么還會有如此多的對象在YGC后存活下來呢?

我們進一步將懷疑對象鎖定在:程序的全局變量或者類靜態變量上。但是diff了本次上線的代碼,我們并未發現代碼中有引入此類變量。

4.對dump的堆內存文件進行分析

代碼排查沒有進展后,我們開始從堆內存文件中尋找線索,使用MAT工具導入了第1步dump出來的堆文件后,然后通過Dominator Tree視圖查看到了當前堆中的所有大對象。

如何實現線上JVM調優立馬發現NewOldMappingService這個類所占的空間很大,通過代碼定位到:這個類位于第三方的client包中,由我們公司的商品團隊提供,用于實現新舊類目轉換(最近商品團隊在對類目體系進行改造,為了兼容舊業務,需要進行新舊類目映射)。

進一步查看代碼,發現這個類中存在大量的靜態HashMap,用于緩存新舊類目轉換時需要用到的各種數據,以減少RPC調用,提高轉換性能。

如何實現線上JVM調優

原本以為,非常接近問題的真相了,但是深入排查發現:這個類的所有靜態變量全部在類加載時就初始化完數據了,雖然會占到100多M的內存,但是之后基本不會再新增數據。并且,這個類早在3月份就上線使用了,client包的版本也一直沒變過。

經過上面種種分析,這個類的靜態HashMap會一直存活,經過多輪YGC后,最終晉升到老年代中,它不應該是YGC持續耗時過長的原因。因此,我們暫時排除了這個可疑點。

5.分析YGC處理Reference的耗時

團隊對于YGC問題的排查經驗很少,不知道再往下該如何分析了。基本掃光了網上可查到的所有案例,發現原因集中在這兩類上:

  • 對存活對象標注時間過長:比如重載了Object類的Finalize方法,導致標注Final Reference耗時過長;或者String.intern方法使用不當,導致YGC掃描StringTable時間過長。

  • 長周期對象積累過多:比如本地緩存使用不當,積累了太多存活對象;或者鎖競爭嚴重導致線程阻塞,局部變量的生命周期變長。

針對第1類問題,可以通過以下參數顯示GC處理Reference的耗時-XX:+PrintReferenceGC。添加此參數后,可以看到不同類型的 reference 處理耗時都很短,因此又排除了此項因素。

如何實現線上JVM調優

6.再回到長周期對象進行分析

再往后,我們添加了各種GC參數試圖尋找線索都沒有結果,似乎要黔驢技窮,沒有思路了。綜合監控和種種分析來看:應該只有長周期對象才會引發我們這個問題。
折騰了好幾個小時,最終峰回路轉,一個小伙伴重新從MAT堆內存中找到了第二個懷疑點。

如何實現線上JVM調優

從上面的截圖可以看到:大對象中排在第3位的ConfigService類進入了我們的視野,該類的一個ArrayList變量中竟然包含了270W個對象,而且大部分都是相同的元素。
ConfigService這個類在第三方Apollo的包中,不過源代碼被公司架構部進行了二次改造,通過代碼可以看出:問題出在了第11行,每次調用getConfig方法時都會往List中添加元素,并且未做去重處理

如何實現線上JVM調優

我們的廣告服務在apollo中存儲了大量的廣告策略配置,而且大部分請求都會調用ConfigService的getConfig方法來獲取配置,因此會不斷地往靜態變量namespaces中添加新對象,從而引發此問題。

至此,整個問題終于水落石出了。這個BUG是因為架構部在對apollo client包進行定制化開發時不小心引入的,很顯然沒有經過仔細測試,并且剛好在我們上線前一天發布到了中央倉庫中,而公司基礎組件庫的版本是通過super-pom方式統一維護的,業務無感知。

7.解決方案

為了快速驗證YGC耗時過長是因為此問題導致的,我們在一臺服務器上直接用舊版本的apollo client 包進行了替換,然后重啟了服務,觀察了將近20分鐘,YGC恢復正常。
最后,我們通知架構部修復BUG,重新發布了super-pom,徹底解決了這個問題。

到此,相信大家對“如何實現線上JVM調優”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

资兴市| 南阳市| 合江县| 渝北区| 垣曲县| 定襄县| 屏边| 宁河县| 德江县| 河池市| 霍州市| 靖西县| 乌拉特后旗| 山东省| 长汀县| 刚察县| 延寿县| 屏南县| 昌宁县| 甘肃省| 石台县| 谢通门县| 通州区| 民权县| 广丰县| 增城市| 苍梧县| 石门县| 桃源县| 封丘县| 汝阳县| 大安市| 福鼎市| 呼和浩特市| 陈巴尔虎旗| 如皋市| 金平| 马尔康县| 定南县| 军事| 益阳市|