您好,登錄后才能下訂單哦!
這篇文章主要介紹了java內存異常使用導致full gc頻繁如何解決的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇java內存異常使用導致full gc頻繁如何解決文章都會有所收獲,下面我們一起來看看吧。
日常巡檢發現,應用線上出現頻繁full gc
應用線上出現頻繁full gc
拉dump文件:小插曲:dump時如果指定:live,則在dump前jvm會先進行一次full gc,并且gc log里會打印dump full gc,這種對非內存泄漏導致的線上異常內存情況排查反而會帶來不便,導致我們多dump了好幾次。
分析dump文件:
a. 發現大量long[]數組占用最大空間,有異常情況
b. 查看gc根節點,發現這些long[]數據大部分是被org.HdrHistogram.Histogram持有,每個Histogram對象會持有一個2048size的long[]
c. 查看Histogram實例的數量,竟然有5w個,對比下正常項目的堆棧,大約是100倍
d. 這里又有一個插曲,一開始習慣用mat分析,但是mat生成的報告對分析泄露比較有用,對于分析異常的內存沒有jvisualvm.exe和idea的profiler好用
本地啟動,可以復現這個類的內存使用情況,于是本地起一個其他內存正常的服務與有問題的應用,分析內存對比
這里用的是idea的profiler,很方便
發現差異:
對比正常的應用,發現異常應用的引用存在異常的來自
● rx.internal.operators.OnSubscribeReduceSeed$ReduceSeedSubscriber的引用,懷疑就是這個異常引用就是導致這些實例無法在新生代回收而是堆積到了老年代觸發full gc的原因
簡單看了下相關代碼,看不出個所以然,直接debug對比
系統確實走進了相關的代碼,增加了對Histogram的引用,而正常應用沒有
但是光這樣也看不出來為什么,此時關注到了左下角的線程池,這個線程池比較奇怪,是Metric的線程池
Metric是Hystrix用來統計相關指標,來供自己的dashboard或者用戶來獲取,以此來了解系統熔斷相關參數和指標的功能
再看堆棧,走到這里的邏輯是
這個流用來統計單位時間內的系統指標,導致Hystrix使用Histogram的long數組實現類似滑動窗口的效果統計單位時間內的指標
Histogram本身是Hystrix用來實現類似桶+滑動窗口的功能,來統計單位時間內的流量,但是因為開啟了指標參數,導致hystrix為了統計更長時間范圍內的指標,新增了對象持有更多(單位時間內)的Histogram引用來聚合,這部分引用因為是統計更長時間范圍周期的,就會因為引用持有時間長而到老年代,但是本質并不是內存泄漏,所以每次full gc后又可以得到回收
看到上面的差異和怪異的線程池,第一反應就是關閉metric使應用不走到這段邏輯中增加引用,看官方文檔,該配置默認是打開的,并且確認該功能只影響指標統計不影響斷路器本身功能,使用配置hystrix.metrics.enabled=false配置來關閉
新增配置后,驗證并查看堆棧,引用恢復正常,并且系統在一段時間后并沒有新增更多的Histogram實例,發布線上后觀察一段時間,full gc問題確實得到解決
在當時發現解決的辦法并驗證后,并沒有時間去研究hystrix.metrics.enabled默認配置就是true但是其他應用沒有出現這個full gc問題的原因, 先解決了之后后續再繼續跟進排查根本原因防止其他項目也出現相同問題
之前發現可疑的線程池是HystrixMetricsPoller ,經過查看,該線程池由HystrixMetricsPollerConfiguration
類開啟,主要依靠hystrix.metrics.enabled開啟,但是默認是true,為什么其他項目沒有開啟呢?
搜了下源碼,這個類的開啟還和一個注解有關
對比了一下代碼,果然只有異常的應用使用了這個注解,這個注解的目的是開啟斷路器
但是研究之后發現,不使用這個注解,熔斷等功能依舊可用,原因是在spring-cloud高版本之后,spring通過使用hystrix封裝openfeign的方法來使用熔斷,而不是集成整個hystrix體系,可能spring-cloud也發現了hystrix內存使用上的問題
所以在較高版本(起碼我們的版本),feign是通過feign.hystrix.enabled來開關斷路器的(這個開關是關閉的話,單純加@EnableCircuitBreaker注解斷路器是不會生效的)
其實在更高點版本的spring-cloud中,@EnableCircuitBreaker這個注解已經被標注為廢棄了,但是可能因為我們是中間版本,所以存在既沒有標注廢棄其實又沒有什么用的情況
總而言之,feign的斷路功能只通過feign.hystrix.enabled來控制,增加@EnableCircuitBreaker注解之后僅僅只是會開啟Hystrix其他所有的指標等功能
關于“java內存異常使用導致full gc頻繁如何解決”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“java內存異常使用導致full gc頻繁如何解決”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。