您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何優(yōu)化JVM OOM”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“如何優(yōu)化JVM OOM”吧!
剛接手的服務(wù),正常穩(wěn)定運(yùn)行了很長(zhǎng)一段時(shí)間,在大家伙收拾東西準(zhǔn)備回家過(guò)年時(shí),突然就抽風(fēng)了。
接口失敗率居高不下?
看日志!
GC overhead limit exceeded
java.lang.OutOfMemoryError:GC overhead limit exceeded
看一下JVM堆棧
sudo jmap -heap port
#eg:sudo jmap -heap 9999
很明顯,是內(nèi)存不夠了。
我當(dāng)時(shí)的第一想法就是,應(yīng)該是內(nèi)存泄漏!我的思路如下:
1、先入為主,因?yàn)橹疤幚磉^(guò)一次因內(nèi)存泄漏導(dǎo)致的JVM OOM問(wèn)題,所以當(dāng)時(shí)高度懷疑內(nèi)存泄漏。
2、導(dǎo)出JVM堆數(shù)據(jù),分析、定位問(wèn)題。
3、fix bug,重新部署,finish!
我按照這個(gè)思路,分析堆棧后,發(fā)現(xiàn)堆中有大量對(duì)象,這些對(duì)象還沒(méi)來(lái)得及回收,其他線程又在申請(qǐng)內(nèi)存,從而導(dǎo)致了OOM。造成問(wèn)題的直接原因是業(yè)務(wù)請(qǐng)求量增加了,而現(xiàn)有的機(jī)器資源不夠用。至于間接原因,下一篇文章再詳細(xì)描述。
在揭開(kāi)問(wèn)題的謎底后,回過(guò)頭想一想,如果當(dāng)時(shí)能夠仔細(xì)分析一下問(wèn)題,或許問(wèn)題會(huì)被更快解決。
事后反思:服務(wù)已經(jīng)穩(wěn)定正常運(yùn)行了一段時(shí)間,且一個(gè)月內(nèi)未修改代碼和更新服務(wù)。如果是代碼有問(wèn)題,那么問(wèn)題極大可能會(huì)在新代碼上線后的幾天內(nèi)出現(xiàn)?;谶@一點(diǎn),基本可以排除代碼問(wèn)題。
線上服務(wù)出現(xiàn)問(wèn)題,首要的任務(wù)就是盡快恢復(fù)服務(wù)可用。如果下次出現(xiàn)類似問(wèn)題,我會(huì)選擇流程一,而非流程二。
造成服務(wù)不可用的直接原因是服務(wù)請(qǐng)求量上升,而根本原因是由于下游服務(wù)負(fù)載過(guò)高,導(dǎo)致微服務(wù)調(diào)用超時(shí),從而引起連鎖反應(yīng)。
下圖呈現(xiàn)了用戶發(fā)起請(qǐng)求到響應(yīng)完成的大致流程。
業(yè)務(wù)服務(wù)接口和算法服務(wù)接口使用eureka作為服務(wù)注冊(cè)中心,整體來(lái)說(shuō),這個(gè)服務(wù)采用相對(duì)簡(jiǎn)單的微服務(wù)架構(gòu)。
服務(wù)接口搭配feign來(lái)請(qǐng)求算法服務(wù)接口。
@FeignClient(value = "image-service")
public interface ImageService {
@PostMapping(value = "/XXX")
String XXX(@RequestParam("img_base64") String imgBase64);
}
上面的代碼在執(zhí)行請(qǐng)求的時(shí)候,會(huì)將請(qǐng)求參數(shù)進(jìn)行拼接。
image-service/xxx?img_base64=fjsfdgldfgrwdfdmgfdglwefsl
當(dāng)eureka真正確定請(qǐng)求的服務(wù)地址后,又會(huì)再做一次拼接處理。
127.0.0.1:5000/xxx?img_base64=fjsfdgldfgrwdfdmgfdglwefsl
算法服務(wù)接口的處理時(shí)間與圖片的大小正相關(guān),圖片越大,處理時(shí)間越長(zhǎng)。由于處理圖片是一個(gè)相對(duì)耗時(shí)的操作,接口會(huì)出現(xiàn)超時(shí)的情況。如果請(qǐng)求失?。ǔ瑫r(shí)),那么feign會(huì)進(jìn)行重試。
圖片base64字符串的長(zhǎng)度與圖片大小呈正相關(guān)關(guān)系,圖片越大,base64字符串長(zhǎng)度越長(zhǎng)。一張306K的圖片,轉(zhuǎn)成base64格式后,字符串長(zhǎng)度為429196。
因此處理一次正常的請(qǐng)求消耗的內(nèi)存比較大。圖片越大,算法處理時(shí)間越久,超時(shí)失敗后,feign重試,重試之后又失敗,導(dǎo)致一個(gè)惡性循環(huán)(幸好有超時(shí)次數(shù)限制,否則如此遞歸下去,后果不堪設(shè)想)。
如圖是JVM OOM后拿到堆棧的數(shù)據(jù),最大的圖片base64的大小有5M。
jdk1.8 JVM參數(shù)PretenureSizeThreshold的默認(rèn)值是2M。
當(dāng)base64字符串超過(guò)2M時(shí),會(huì)直接分配到老年代,這無(wú)疑加大了JVM老年代的內(nèi)存壓力,導(dǎo)致頻繁Full GC。
為何使用image base64傳輸圖片?
1、歷史原因。
2、開(kāi)發(fā)相對(duì)簡(jiǎn)單。
該如何優(yōu)化?
1、提高feign請(qǐng)求的超時(shí)時(shí)間。
2、提高機(jī)器配置。
3、將image base64放到請(qǐng)求體中,減少因feign框架對(duì)參數(shù)進(jìn)行拼接帶來(lái)的內(nèi)存開(kāi)銷。
感謝各位的閱讀,以上就是“如何優(yōu)化JVM OOM”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)如何優(yōu)化JVM OOM這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。