偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

不會JVM調(diào)優(yōu)怎么進互聯(lián)網(wǎng)大廠

開發(fā) 前端
那么JVM到底應(yīng)該怎樣調(diào)優(yōu)呢?有沒有什么套路我們可以學習?本文主要著眼于如何進行參數(shù)預(yù)估以及JVM優(yōu)化,希望對大家平時工作可以有所裨益。

如果說有什么在面試中經(jīng)常被問到,但是在實際工作中又不經(jīng)常用到的Java技術(shù),那么JVM調(diào)優(yōu)絕對可以排得上號。每當有同學被問到這個問題的時候,內(nèi)心的OS大概是這樣:我一個QPS幾百的系統(tǒng),有啥好調(diào)優(yōu)的,默認配置用用得了,調(diào)JVM參數(shù)整不好系統(tǒng)還能干崩了,想想好像是這么個道理。但是對于一些高并發(fā)大流量業(yè)務(wù)場景,JVM調(diào)優(yōu)就有用武之地了。因此個人覺得JVM調(diào)優(yōu)也許不像SQL調(diào)優(yōu)或者代碼優(yōu)化在工作中使用得那么頻繁,甚至很多時候其實是用不上的,但是在需要用到的時候如果你能頂?shù)米毫ν瓿蓛?yōu)化,那么你和其他人的不同就顯現(xiàn)出來了。另外如果我們想進入一線互聯(lián)網(wǎng)大廠,那么JVM調(diào)優(yōu)就是必須要掌握的重要技能。

那么JVM到底應(yīng)該怎樣調(diào)優(yōu)呢?有沒有什么套路我們可以學習?本文主要著眼于如何進行參數(shù)預(yù)估以及JVM優(yōu)化,希望對大家平時工作可以有所裨益。

圖片

預(yù)估比調(diào)優(yōu)更重要

為什么需要進行預(yù)估

所謂凡事預(yù)則立不預(yù)則廢,對于JVM調(diào)優(yōu)來說也是如此。無論修改線上已有JVM參數(shù)配置還是優(yōu)化代碼實際都是一種無奈之舉,因為生產(chǎn)環(huán)境出現(xiàn)了運行異常不得不采用這種方式進行優(yōu)化,從而保障線上應(yīng)用服務(wù)能夠正常運行,否則就要拉程序員出來祭天了。但是如果我們在服務(wù)發(fā)布部署之前可以預(yù)估服務(wù)的容量而后進行對應(yīng)的JVM參數(shù)配置,那么就相當于把可能出現(xiàn)的JVM異常扼殺在搖籃中。當然這是最理想的狀態(tài),在現(xiàn)實中也實際不容易做到,但是即便我們不能預(yù)估的那么準確,也總比不做容量預(yù)估直接裸奔上線的好。因此關(guān)于JVM調(diào)優(yōu)這件事情,實際和《孫子兵法》的核心思想有異曲同工之妙,上兵伐謀,其次伐交,其次伐兵,其下攻城。也就是說JVM調(diào)優(yōu)最高境界是預(yù)估不調(diào),打仗最高境界是不戰(zhàn)而勝。

如何進行預(yù)估

JVM參數(shù)預(yù)估基本流程

在明確了JVM參數(shù)預(yù)估對于生產(chǎn)環(huán)境中服務(wù)穩(wěn)定運行的意義之后,我們一起看下如何進行JVM參數(shù)預(yù)估。首先我們應(yīng)該先分析下自己系統(tǒng)的核心業(yè)務(wù)流程是什么,然后根據(jù)核心業(yè)務(wù)流程結(jié)合線上可能的流量,確認好我們核心業(yè)務(wù)代碼中的對象創(chuàng)建以及銷毀情況是怎樣的,最后再針對性的進行相關(guān)JVM參數(shù)的預(yù)估配置。因此JVM參數(shù)預(yù)估的地址基本流程如下所示:

圖片

案例驅(qū)動

這里以一個實際的業(yè)務(wù)場景案例來幫助大家更好理解JVM參數(shù)預(yù)估的過程。假設(shè)有這樣一個電商平臺,它主要由商品中心、訂單中心、營銷中心、庫存中心等子系統(tǒng)組成。那對于電商系統(tǒng)來說最核心的業(yè)務(wù)就是用戶下單購物,我們就以用戶下單購物這個業(yè)務(wù)流程來看看如何進行估算JVM參數(shù)。

假設(shè)平臺有1個億的注冊用戶,日活用戶1000萬,這些用戶會在電商平臺進行瀏覽商品、下單購買以及收貨評價等操作,但是實際上真正下單購買的用戶并沒有那么多,如果有10%的轉(zhuǎn)化率,那么就相當于每天電商平臺有100w個訂單。另外一般情況下這些訂單主要分布在一天當中的高峰時間,比如中午或者晚上,畢竟其他時間大家要忙碌工作以及其他事情,中午休息或者晚上休息的時候才會有時間逛平臺買買買。如果我們把用戶購買的高峰時間定為3小時,也就是說極端情況下將所有的訂單的生成都分布在這三個小時中完成,也就是每小時產(chǎn)生33萬個訂單,每秒產(chǎn)生92個訂單左右。

在估算訂單對象大小之前,我們先來看下堆中的對象由哪些元素組成。一個JVM對象的大小主要由三部分組成,分別是對象頭、數(shù)據(jù)以及數(shù)據(jù)補齊。對象頭以及對象補齊基本變化不大,因此對象的大小實際和對象中的屬性有直接關(guān)系,對象中的屬性越多,對象占用的空間大小也就越大。

Mark Word:主要存儲對象自身的運行數(shù)據(jù),包括HashCode、GC分代年齡鎖狀態(tài)標志、線程持有的鎖等信息,根據(jù)操作系統(tǒng)位數(shù)的不同而不同,32位的操作系統(tǒng)對應(yīng)的大小就是32bit,64位的操作系統(tǒng)對應(yīng)的大小就是64bit;

Klass Pointer:指向?qū)ο髮?yīng)的Class對象的內(nèi)存地址,根據(jù)不同的操作數(shù)系統(tǒng)占用空間不同,在64位系統(tǒng)中占用8個字節(jié);

Array Length:如果當前對象是一個數(shù)組對象那么此處存儲的就是數(shù)組的大小,占用4個字節(jié),如果不是數(shù)組對象那么就不占用。

圖片

回到我們剛才的案例當中,我們來具體估算一個訂單對象大概占多少內(nèi)存空間。訂單對象主要包括了如下的屬性:訂單編號、商品編號、商品價格、創(chuàng)建時間、付款時間以及發(fā)貨時間等,當然實際訂單可能不止這些屬性,我們只是說明對象大小估算的方法,因此對屬性進行了相應(yīng)的裁剪。如果數(shù)據(jù)層面包含了這些屬性,那么數(shù)據(jù)部分的占用空間大小就是這些屬性的大小總和。總共估算下來應(yīng)該不到1kb,但是實際考慮到其他各種占用以及平臺中肯定不止訂單這一種對象,還會有庫存對象、積分對象、物流對象、營銷對象等等,因此我們考慮將對象的總和擴大30倍進行估算,也就是說平臺中產(chǎn)生的各種對象的總和為30乘以1kb即為30kb。如果每秒產(chǎn)生92個對象的話,那么就相當于每秒產(chǎn)生2760kb的對象,也就是大概2Mb的對象,另外由于電商平臺中布置下單這一個操作,還會包含訂單查詢、商品查詢等等其他業(yè)務(wù)那么綜合起來我們再放大10倍,也就是說每秒JVM中新增20Mb左右的對象。對于一臺4核8G的服務(wù)器來說,我們可以為服務(wù)分配3G左右的堆內(nèi)存,512Mb左右的元空間。

但是考慮到電商平臺存在大促場景,這個時候的流量可能是平時的好幾倍,因此我們實際上需要將堆內(nèi)存中的年輕代進行放大,Eden區(qū)可以到1.6G,Survivor區(qū)可以各自200M。這樣可以避免由于年輕代空間不足導致對象提前進入老年代而造成fullGC的頻率變高,從而影響服務(wù)的穩(wěn)定性。

JVM調(diào)優(yōu)思路JVM

理想情況下預(yù)估的JVM參數(shù)應(yīng)該可以cover線上的業(yè)務(wù)場景,但是假如公司業(yè)務(wù)發(fā)展飛快,業(yè)務(wù)體量迅速膨脹,原先預(yù)估的JVM配置參數(shù)可就不一定能滿足線上生產(chǎn)環(huán)境所有情況,因此異常情況還是會出現(xiàn)。這里將JVM異常主要分為兩類,一種是代碼導致的JVM異常,另一種是JVM不合理配置導致的異常,包括JVM參數(shù)以及服務(wù)器內(nèi)存配置。

代碼導致的JVM異常

代碼Bug應(yīng)該是導致JVM異常最常見的情況,這種情況我們只能通過調(diào)整代碼才能實現(xiàn)優(yōu)化,因為即使臨時調(diào)整JVM參數(shù)也只是緩兵之計,并沒有根除問題所在,隨著時間的推移,業(yè)務(wù)的發(fā)展問題還是會暴露。所以要想解決根本問題還是需要定位問題代碼來進行優(yōu)化。

那么首先我們就需要能夠有手段定位到到底哪部分代碼導致JVM異常。一般分為兩種情況,一種就是已經(jīng)發(fā)生內(nèi)存溢出了,另一種是還沒有發(fā)生內(nèi)存溢出但是已經(jīng)在崩潰的邊緣,系統(tǒng)響應(yīng)也變慢了。如果我們配置了-XX:HeapDumpPath參數(shù),當JVM發(fā)生內(nèi)存溢出的時候就可以到對應(yīng)的目錄去找到hprof文件。如果還沒有發(fā)生內(nèi)存溢出,這個時候我們可以通過操作命令jmap -dump:format=b,file=/tmp/文件名.hprof <PID>來手動導出內(nèi)存快照來進行進行分析。有了hprof文件之后,我們可以通過MAT工具來分析和定位內(nèi)存溢出代碼位置,然后再進行針對性的優(yōu)化。

Java代碼引起的JVM異??梢苑譃橐韵聨追N情況,我們一起來看看有哪些:

(1)如下圖的例子,客戶端和服務(wù)端建立了websocket連接,如果連接未正常建立,又重新建立連接如果此時服務(wù)端未將連接關(guān)閉,那么就會導致重新使用新的請求對象,隨著時間的累計JVM中出現(xiàn)大量對象來不及回收,導致JVM無法分配新的內(nèi)存空間給服務(wù)中新產(chǎn)生的對象,最終導致JVM內(nèi)存溢出。由于JVM中堆積了幾千個RequestIInfo對象,同時服務(wù)還在不斷產(chǎn)生新的RequestInfo對象,最終不可避免地就會發(fā)生OutOfMemoryError異常。通過MAT我們可以輕松定位到發(fā)生內(nèi)存溢出的代碼位置,搞清楚為什么會有RequestInfo對象被創(chuàng)建之后,我們就可以進行針對性的優(yōu)化了。

圖片

(2)我們在實際項目開發(fā)的過程中必定會涉及到業(yè)務(wù)數(shù)據(jù)的查詢,假如沒有控制好數(shù)據(jù)查詢的條件或者說本身查詢的數(shù)據(jù)量就很大。那么就容易造成一次性查詢大量數(shù)據(jù),這些數(shù)據(jù)如果全部load到內(nèi)存中就很容易導致內(nèi)存溢出。所以一般涉及到數(shù)據(jù)查詢的代碼要做好相應(yīng)的處理,分頁查詢也好,限制查詢數(shù)據(jù)量也好或者流式查詢也好,總之不能一次性將大量數(shù)據(jù)加載到內(nèi)存中。

(3)在for循環(huán)或者while循環(huán)中大量創(chuàng)建對象,最終導致對象在對堆內(nèi)存中堆積,這種是由于條件沒有控制好條件導致對象被不斷創(chuàng)建。

(4)我們都知道JVM運行時數(shù)據(jù)區(qū)的虛擬機棧是線程所獨有的,JVM啟動后會為每個線程的虛擬機棧分配固定大小的內(nèi)存(-Xss參數(shù)),因此虛擬機棧的深度是確定的,如果代碼中出現(xiàn)不合理的遞歸代碼,就會造成虛擬機棧只入棧不出棧,最終導致虛擬機棧內(nèi)存空間被耗盡,從而產(chǎn)生StackOverFlowError。

當我們知道了這些常見的可能導致JVM異常的代碼結(jié)構(gòu)之后,那么在平常做項目編寫代碼的時候就要時刻保持警惕。寫完代碼之后自己再回頭看看這段代碼的對象創(chuàng)建情況是怎樣的,有沒有大對象緩存,有沒有不合理的while循環(huán)for循環(huán),會不會有可能造成JVM內(nèi)存溢出。當我們有了這樣反觀代碼的意識之后,從根本上JVM內(nèi)存溢出的概率大大降低,有益于線上服務(wù)的穩(wěn)定性。

JVM參數(shù)不合理導致的異常

線上環(huán)境JVM參數(shù)不合理直接影響JVM運行穩(wěn)定性。我們都知道對象都是存放在堆內(nèi)存中的,而堆內(nèi)存又被劃分為年輕代和老年代,新產(chǎn)生的對象都會被分配在年輕代對應(yīng)的堆內(nèi)存中,如果此時我們設(shè)置的年輕代過小。那么對象進入到老年代堆空間的概率就會增大,當然引起full GC的可能性也會大大增加。因此JVM參數(shù)如果設(shè)置的不合理一般是堆內(nèi)存大小、元數(shù)據(jù)區(qū)大小以及垃圾回收器。另外我們需要根據(jù)不同的業(yè)務(wù)場景來選擇對應(yīng)的垃圾回收器,如果對于停頓時間有比較高的要求可以考慮G1和ZGC。

通過上文我們可以明確無論是優(yōu)化業(yè)務(wù)代碼還是參數(shù)調(diào)優(yōu),其實都是在避免在堆中遺留過多的對象??梢钥吹贸鰜?,JVM調(diào)優(yōu)的本質(zhì)思想其實就是生產(chǎn)者-消費者模型,為什么這么說呢?你看一方面隨著平臺業(yè)務(wù)的不斷進行,JVM中會不斷產(chǎn)生對象,那么平臺就相當于對象生產(chǎn)者。另一方面垃圾回收器這個勤勞的小蜜蜂在不斷檢測哪些對象已經(jīng)是垃圾對象,然后根據(jù)策略進行垃圾回收釋放內(nèi)存空間,那么JVM就相當于對象消費者。一個生產(chǎn)對象,一個消費對象,這可不就是生產(chǎn)者消費者模型嘛。所以從這個角度來看,生產(chǎn)者和消費者的動態(tài)平衡才能保證JVM的正常運行,如果對象生產(chǎn)地快,而對象回收地慢就會導致內(nèi)存溢出等JVM異常。所以JVM調(diào)優(yōu)從本質(zhì)上來說,就是通過各種手段構(gòu)建對象生產(chǎn)與回收的動態(tài)平衡。

JVM常見配置參數(shù)

無論是發(fā)布部署前的JVM參數(shù)預(yù)估還是異常過后的參數(shù)優(yōu)化,都是需要通過調(diào)節(jié)JVM對應(yīng)的參數(shù)來完成的,因此我們需要掌握常用JVM參數(shù)項及其含義。

配置項

含義

-Xms

初始堆大小

-Xmx

初始堆最大值

-Xmn

堆中新生代最大值

-XX:SurvivorRatio

survivor區(qū)與Eden區(qū)的比例

-XX:NewRatio

新生代和老年代的比例

-XX:MetaspaceSize

初始元空間大小

-XX:MaxMetaspaceSize

元空間最大大小

-Xss

線程虛擬機棧大小

-XX:+HeapDumpOnOutOfMemoryError

開啟內(nèi)存溢出時進行內(nèi)存快照

-XX:HeapDumpPath=/data/dump/jvm.hprof

內(nèi)存快照文件路徑

JVM常見垃圾回收器

隨著JDK版本的不斷迭代,垃圾回收器同樣也在不斷迭代優(yōu)化。當然不同的業(yè)務(wù)場景,我們可以選擇不同的垃圾回收器來進行應(yīng)對,而垃圾回收器也在向著回收效率高、停頓時間短的目標不斷進行調(diào)整改進。

垃圾回收器

引入版本

特點

適用場景

Serial GC

JDK3

單線程方式進行垃圾回收,暫停所有應(yīng)用線程

適用于小型應(yīng)用,單CPU的系統(tǒng)或者不需要高并發(fā)的場景

ParNew GC

JDK3

Serial GC多線程實現(xiàn)

年輕代垃圾回收

Parallel GC

JDK4

利用多CPU、多核心的系統(tǒng)資源,提高垃圾回收效率

對吞吐量有要求的應(yīng)用場景,如數(shù)據(jù)處理、科學計算等

CMS GC

JDK5

采用多線程方式進行垃圾回收,能夠縮短應(yīng)用程序的暫停時間

適用于對響應(yīng)時間有要求的應(yīng)用場景

G1 GC

JDK7

內(nèi)存劃分為一個個Region,可以指定停頓時間

適用于部署早多核CPU大內(nèi)存機器上的大型應(yīng)用,對停頓時間有一定要求,

ZGC

JDK11

支持超大堆空間,最大停頓時間不超過10ms

業(yè)務(wù)對于停頓時間低于100ms

總結(jié)

任何技術(shù)上的優(yōu)化都是建立在對技術(shù)原理的深刻理解基礎(chǔ)之上的,JVM調(diào)優(yōu)亦是如此。文章中常見的JVM調(diào)優(yōu)手段只不過是一些術(shù),搞懂JVM的運行原理以及垃圾回收機制才是關(guān)鍵。另外在調(diào)優(yōu)前我們得先搞清楚我們調(diào)優(yōu)的目標是什么,有了目標的指引,我們才能做到有的放矢。其實無論是性能優(yōu)化還是業(yè)務(wù)優(yōu)化其實都是有一定的規(guī)律可以摸索,萬變不離其宗,都是通過觀:觀察當前是個什么樣的狀態(tài);析:分析整條業(yè)務(wù)鏈路找到可以優(yōu)化的方向以及改造點;優(yōu):動手制定優(yōu)化策略以及驗證方法進行優(yōu)化實操。

責任編輯:姜華 來源: 慕楓技術(shù)筆記
相關(guān)推薦

2021-12-16 10:32:04

APP會員互聯(lián)網(wǎng)大廠用戶

2022-01-05 16:45:22

互聯(lián)網(wǎng)裁員危機

2022-08-31 16:17:21

造芯互聯(lián)網(wǎng)公司大廠

2020-02-23 17:39:21

互聯(lián)網(wǎng)復工公司

2021-12-14 15:27:48

互聯(lián)網(wǎng)程序員裁員

2022-06-01 20:24:25

互聯(lián)網(wǎng)元宇宙大廠

2018-08-23 09:06:18

互聯(lián)網(wǎng)百度面試

2020-07-19 10:06:02

互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)

2021-11-22 10:03:47

互聯(lián)網(wǎng)薪資技術(shù)

2022-02-24 11:05:06

互聯(lián)網(wǎng)加班科技

2019-10-25 15:50:06

MySQL數(shù)據(jù)庫命令

2022-01-24 10:46:40

互聯(lián)網(wǎng)裁員

2021-06-28 08:57:29

快手騰訊員工

2019-12-09 16:09:00

互聯(lián)網(wǎng)

2019-12-11 15:45:49

互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)

2023-01-17 09:41:26

Redis接口限流

2011-09-05 13:59:15

中國網(wǎng)民互聯(lián)網(wǎng)

2021-12-23 15:21:15

互聯(lián)網(wǎng)大佬隱退

2022-04-12 13:00:25

互聯(lián)網(wǎng)第一創(chuàng)始人隱退

2020-12-30 05:36:59

分庫分表存儲
點贊
收藏

51CTO技術(shù)棧公眾號