Java詳解線上內(nèi)存暴漲問(wèn)題定位和解決方案
前因:
因?yàn)镽EST規(guī)范,定義資源獲取接口使用GET請(qǐng)求,參數(shù)拼接在url上。
如果按上述定義,當(dāng)參數(shù)過(guò)長(zhǎng),超過(guò)tomcat默認(rèn)配置 max-http-header-size :8kb
會(huì)報(bào)一下錯(cuò)誤信息:
Request header is too large
可以修改springboot配置,調(diào)整請(qǐng)求頭大小
server: max-http-header-size: xxx
后果:
如果max-http-header-size設(shè)置過(guò)大,會(huì)導(dǎo)致接口吞吐下降,jvm oom,內(nèi)存泄漏。
因?yàn)閠omcat 會(huì)用HeapByteBuffer 預(yù)分配請(qǐng)求頭內(nèi)存大小,在堆上分配。
請(qǐng)求和響應(yīng)都是一樣的配置,每次請(qǐng)求處理預(yù)先分配,2倍配置值內(nèi)存大小在 jvm 堆中
請(qǐng)求過(guò)多,導(dǎo)致線上內(nèi)存暴漲,老年代有3GB多。使用jmap dump線上內(nèi)存數(shù)據(jù),使用 JProfiler 分析。
符合配置大小和源碼對(duì)象
數(shù)組有3GB,和老年代和eden區(qū)總和大小相近。
-XX:PretenureSizeThreshold jvm參數(shù)用來(lái)設(shè)置默認(rèn)值,當(dāng)數(shù)組或?qū)ο蟠笮〕^(guò)這個(gè)設(shè)定值,直接在 Old Gen 老年代分配;默認(rèn)值0,當(dāng)超過(guò)eden區(qū)的大小的時(shí)候,直接分配到old區(qū)。
使用 java -XX:+PrintCommandLineFlags -version
發(fā)現(xiàn)并沒(méi)有使用
-XX:PretenureSizeThreshold參數(shù),所以是
max-http-header-size設(shè)置過(guò)大,eden區(qū)分配不夠,直接分配到old區(qū),堆區(qū)內(nèi)存不夠,自動(dòng)擴(kuò)容,導(dǎo)致old區(qū)數(shù)據(jù)越來(lái)越多,頻繁觸發(fā)FullGC。
JVM初始分配的內(nèi)存由-Xms指定,默認(rèn)是物理內(nèi)存的1/64;JVM最大分配的內(nèi)存由-Xmx指定,默認(rèn)是物理內(nèi)存的1/4。默認(rèn)空余堆內(nèi)存小 于40%時(shí),JVM就會(huì)增大堆直到-Xmx的最大限制;空余堆內(nèi)存大于70%時(shí),JVM會(huì)減少堆直到-Xms的最小限制。因此服務(wù)器一般設(shè)置-Xms、 -Xmx相等以避免在每次GC后調(diào)整堆的大小。
其中http-nio-9005-exec-線程有146個(gè),和前面配置需要分配的20M內(nèi)存請(qǐng)求,相乘的數(shù)據(jù)與3000MB相近。
tomcat任務(wù)線程池 最大線程數(shù)200,存活時(shí)間60s
因?yàn)門(mén)askQueue 重寫(xiě)了offer方法,在線程池大小小于最大線程數(shù)時(shí),任務(wù)不會(huì)放入任務(wù)隊(duì)列,只會(huì)交給現(xiàn)有線程執(zhí)行;存活時(shí)間60s,只有當(dāng)線程空閑60s才會(huì)被回收,也就是**60秒內(nèi)請(qǐng)求要小于當(dāng)前線程數(shù),**才會(huì)有空閑線程。這就導(dǎo)致了線程不能及時(shí)被回收。請(qǐng)求數(shù)下降,但是內(nèi)存還是居高不下。
解決方案:
max-http-header-size修改為默認(rèn)值,接口請(qǐng)求方式修改為POST,請(qǐng)求參數(shù)放置于body
到此這篇關(guān)于Java詳解線上內(nèi)存暴漲問(wèn)題定位和解決方案的文章就介紹到這了,更多相關(guān)Java 內(nèi)存暴漲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中統(tǒng)計(jì)字符個(gè)數(shù)以及反序非相同字符的方法詳解
本篇文章是對(duì)Java中統(tǒng)計(jì)字符個(gè)數(shù)以及反序非相同字符的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05java中自定義Spring Security權(quán)限控制管理示例(實(shí)戰(zhàn)篇)
本篇文章主要介紹了java中自定義Spring Security權(quán)限控制管理示例(實(shí)戰(zhàn)篇) ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02第三方包jintellitype實(shí)現(xiàn)Java設(shè)置全局熱鍵
本文主要介紹了,在java中使用第三方插件包jintellitype來(lái)實(shí)現(xiàn)全局熱鍵,非常的簡(jiǎn)單,但是很實(shí)用,有需要的朋友可以參考下,歡迎一起來(lái)參與改進(jìn)此項(xiàng)目2014-09-09SpringBoot2.x入門(mén)教程之引入jdbc模塊與JdbcTemplate簡(jiǎn)單使用方法
這篇文章主要介紹了SpringBoot2.x入門(mén)教程之引入jdbc模塊與JdbcTemplate簡(jiǎn)單使用方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Spring Data Redis對(duì)象緩存序列化問(wèn)題解決
相信在項(xiàng)目中,你一定是經(jīng)常使用Redis,在使用時(shí),有沒(méi)有遇到同我一樣,對(duì)象緩存序列化問(wèn)題的呢,本文主要介紹了Spring Data Redis對(duì)象緩存序列化問(wèn)題解決,感興趣的可以了解一下2024-01-01go語(yǔ)言題解LeetCode88合并兩個(gè)有序數(shù)組示例
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode88合并兩個(gè)有序數(shù)組示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12