压力测试与服务端调优(1)
壓力測(cè)試與服務(wù)端調(diào)優(yōu)
- 環(huán)境準(zhǔn)備
- 數(shù)據(jù)庫(kù)
- 秒殺工程
- 服務(wù)打包
- 服務(wù)部署
- 壓力測(cè)試與性能分析
- 壓力測(cè)試維度
- Jmeter工具
- Jmeter下載安裝
- 下載Jmeter插件
- 壓力測(cè)試
- 定制壓測(cè)
- 開(kāi)始測(cè)試
- 并發(fā)測(cè)試
- TPS性能曲線圖
- RT(Response Time)
- 聚合報(bào)告
- 性能分析
- CPU
- 內(nèi)存
- 磁盤(pán)
- 網(wǎng)絡(luò)
- 服務(wù)端調(diào)優(yōu)
- Tomcat調(diào)優(yōu)
- 問(wèn)題1
- 問(wèn)題2
- 問(wèn)題3
- KeepAlive
- JVM調(diào)優(yōu)
- 為什么要進(jìn)行JVM調(diào)優(yōu)
- 調(diào)優(yōu)原則
- 調(diào)優(yōu)原理
- 什么是垃圾?
- 怎么找垃圾?
- 如何清除垃圾?
- 標(biāo)記-清除
- 復(fù)制
- 標(biāo)記-整理
- 分代收集
- 垃圾回收器
- 特點(diǎn)
- 常用垃圾回收器組合
- 垃圾回收器原理
- Serial + Serial old
- Parallel Scavenge + Parallel old
- ParNew + CMS
- G1
- 內(nèi)存分代模型
- JVM實(shí)戰(zhàn)調(diào)優(yōu)
- 典型參數(shù)設(shè)置
- GC日志輸出
- GC日志分析
- JVM內(nèi)存使用情況
- 關(guān)鍵指標(biāo)
- 存在問(wèn)題
- Full GC頻繁發(fā)生
- Young & Old 比例
- Eden & S0 & S1
- 總結(jié)
- GC組合
- 吞吐量?jī)?yōu)先
- 響應(yīng)時(shí)間優(yōu)先
- G1
環(huán)境準(zhǔn)備
數(shù)據(jù)庫(kù)
- 使用自己本機(jī)的虛擬機(jī)安裝,虛擬機(jī)配置:4核4G。
- MySQL:192.168.254.128:3306
- Redis:192.168.254.128:6379
秒殺工程
- github地址:https://github.com/shouwangyw/vshop-seckill
服務(wù)打包
- 這里我們進(jìn)行服務(wù)部署時(shí),采用手動(dòng)打包的方式,還沒(méi)有使用 jenkins 來(lái)進(jìn)行打包部署,后面再進(jìn)行微服務(wù)改造時(shí)再使用 jenkins 進(jìn)行打包部署。
- 項(xiàng)目打包的時(shí)候: 必須引入以下的插件,否則打包將會(huì)出現(xiàn)依賴(lài)包無(wú)法打包到項(xiàng)目中。
服務(wù)部署
- 后端服務(wù)部署命令:
- 注意:--spring.config.addition-location=application.yml 加載外掛配置文件,為了方便服務(wù)的部署(本地開(kāi)發(fā),測(cè)試都是使用外網(wǎng)IP進(jìn)行測(cè)試),服務(wù)部署必須使用內(nèi)網(wǎng)IP地址,為了不再重新打包部署,使用外掛的配置文件。
- 外掛配置文件:MySQL 和 Redis 的 IP 都修改為 127.0.0.1
- 查看日志:啟動(dòng)成功
- 測(cè)試訪問(wèn)下 swagger 文檔地址:http://192.168.254.128:9000/doc.html,首先登陸獲取token,然后測(cè)一下獲取商品詳情信息的接口:
- 接口是OK的!
壓力測(cè)試與性能分析
- 壓力測(cè)試:及時(shí)發(fā)現(xiàn)系統(tǒng)問(wèn)題,系統(tǒng)瓶頸(預(yù)期系統(tǒng)達(dá)到的吞吐能力),及時(shí)對(duì)系統(tǒng)進(jìn)行優(yōu)化改進(jìn),對(duì)系統(tǒng)的問(wèn)題進(jìn)行修復(fù),因此壓力測(cè)試在整個(gè)項(xiàng)目研發(fā)中非常重要。
- 架構(gòu)師:掌握一定的壓力測(cè)試方法,壓力測(cè)試是保障軟件高質(zhì)量交付手段之一。主要模擬海量的用戶的并發(fā),測(cè)試系統(tǒng)在高并發(fā)模式下,系統(tǒng)響應(yīng)時(shí)間、TPS、BUG 等問(wèn)題。
壓力測(cè)試維度
- 負(fù)載測(cè)試:確定系統(tǒng)在連續(xù)的負(fù)載壓力模式下(梯形壓力施加模式,逐漸增加壓力),是否能堅(jiān)持多少時(shí)間;評(píng)估系統(tǒng)性能:TPS 。
- 強(qiáng)度測(cè)試:極限施壓,使得服務(wù)器一直處于滿負(fù)荷的狀態(tài);測(cè)試系統(tǒng)在滿負(fù)荷的狀態(tài)運(yùn)行情況(運(yùn)行是否穩(wěn)定)。
- 容量測(cè)試:確定系統(tǒng)可以同時(shí)在線的用戶數(shù)量。
Jmeter工具
- 測(cè)試工具:
- AB 測(cè)試工具
- ngrinter 壓力測(cè)試工具
- 阿里云測(cè)試服務(wù)(阿里云施加機(jī)器)
- jmeter工具,可視化的效果
注意問(wèn)題: 開(kāi)始?jí)毫y(cè)試之前,必須思考?jí)毫C(jī)的問(wèn)題?施加多大的壓力,單機(jī)壓力是否足夠?壓力測(cè)試干擾問(wèn)題(網(wǎng)絡(luò)干擾)。
Jmeter下載安裝
- jmeter鏡像下載地址:https://jmeter.apache.org/
下載Jmeter插件
- 下載地址:http://jmeter-plugins.org/downloads/all/,官網(wǎng)上下載 plugins-manager.jar 直接在線下載,然后執(zhí)行在線下載即可。
- 注意:下載插件在英文模式下下載,如果在中文模式下下載,貌似不好使
- 在線下載方法如下圖所示:
- 還可以選擇jmter語(yǔ)言:
- 修改jmeter默認(rèn)語(yǔ)言:
壓力測(cè)試
定制壓測(cè)
- 新建測(cè)試計(jì)劃:
- 添加取樣器:為了方便測(cè)試,這里將代碼中攔截器配置去掉了,即不需要token校驗(yàn)。
- 繼續(xù)添加監(jiān)聽(tīng)器:察看結(jié)果樹(shù)、聚合報(bào)告、TPS、RT等
開(kāi)始測(cè)試
- 使用jmeter進(jìn)行壓力測(cè)試,查看幾個(gè)性能指標(biāo): TPS、RT、聚合報(bào)告。
并發(fā)測(cè)試
TPS性能曲線圖
- 根據(jù) TPS 性能曲線圖:TPS 在 2400 左右,目前該接口只是做了一個(gè)簡(jiǎn)單的主鍵查詢(xún)。
- TPS:從發(fā)送請(qǐng)求到獲取到響應(yīng)結(jié)果的一次請(qǐng)求,叫做一次 TPS。
- QPS:每秒查詢(xún)數(shù),大多數(shù)的情況下,QPS = TPS。
- 例如:訪問(wèn)一個(gè)頁(yè)面 /index.html 是,可能還要加載一些 js、css,那么 QPS = 3、TPS = 1。如果把聚焦的點(diǎn):主關(guān)注接口,QPS = TPS。
RT(Response Time)
- RT:一個(gè)請(qǐng)求從發(fā)送到響應(yīng)耗時(shí)。
- 可以看到,大部分請(qǐng)求都在 1、2 秒左右返回,響應(yīng)時(shí)間并不是很理想。主要是因?yàn)榉?wù)部署在本地 VMware 虛擬機(jī),測(cè)試機(jī)也都是在本地。
聚合報(bào)告
- #樣本: 20w 個(gè)樣本
- #平均值:所有請(qǐng)求平均耗時(shí) 1576ms
- #中位數(shù):50%的請(qǐng)求在 1552ms 之內(nèi)響應(yīng)結(jié)束
- #90%百分位:90%的請(qǐng)求在 1876ms 之內(nèi)響應(yīng)結(jié)束
- #最小值:請(qǐng)求的最小耗時(shí) 0ms
- #最大值:請(qǐng)求的最大耗時(shí) 10018ms
- #異常率:發(fā)送異常頻率
性能分析
系統(tǒng)出現(xiàn)問(wèn)題分類(lèi):
- 系統(tǒng)異常:CPU占用率高、磁盤(pán)滿了、磁盤(pán)IO頻繁、網(wǎng)絡(luò)流量異常等;排查指令:top、free、dstat、pstack、vmstat、strace 獲取異常信息,排查系統(tǒng)異常情況。
- 業(yè)務(wù)異常:流量太多系統(tǒng)扛不住、耗時(shí)長(zhǎng)、線程死鎖、多線程并發(fā)問(wèn)題、頻繁full gc、oom等;排查指令:top、jstack、pstack、strace、日志等。
CPU
- top 指令監(jiān)控 CPU 使用情況,根據(jù) CPU 使用情況分析系統(tǒng)整體運(yùn)行情況:
- 關(guān)注指標(biāo):load average 代表系統(tǒng)的繁忙程度,三個(gè)參數(shù)分別是 1 分鐘、5 分鐘、15 分鐘 CPU 的平均負(fù)載。
- 單核CPU:
- Load average < 1 , cpu比較空閑,沒(méi)有出現(xiàn)線程等待cpu執(zhí)行現(xiàn)象;
- Load average = 1 , cpu剛剛占滿,沒(méi)有空閑空間;
- Load average > 1 , cpu已經(jīng)出現(xiàn)了線程等待,比較繁忙;
- Load average > 3 , cpu阻塞非常嚴(yán)重,出現(xiàn)了嚴(yán)重線程等待,必須進(jìn)行優(yōu)化處理。
- 4和CPU:
- Load average < 4 , cpu比較空閑,沒(méi)有出現(xiàn)線程等待cpu執(zhí)行現(xiàn)象;
- Load average = 4 , cpu剛剛占滿,沒(méi)有空閑空間;
- Load average > 4 , cpu已經(jīng)出現(xiàn)了線程等待,比較繁忙;
- Load average > 9 , cpu阻塞非常嚴(yán)重,出現(xiàn)了嚴(yán)重線程等待,必須進(jìn)行優(yōu)化處理。
內(nèi)存
- free 指令排查線上問(wèn)題重要指令,內(nèi)存問(wèn)題很多時(shí)候是引起 CPU 較高的原因。
磁盤(pán)
- df 指令查看磁盤(pán)使用情況,有時(shí)候服務(wù)出現(xiàn)問(wèn)題,可能就是磁盤(pán)不夠了。
網(wǎng)絡(luò)
- dstat 指令:其集成了 vmstat、iostat、netstat 等工具的特色。使用該命令需要先進(jìn)行安裝:
- -c 查看cpu情況;-d 磁盤(pán)讀寫(xiě);-n 網(wǎng)絡(luò)狀態(tài);-l 顯示系統(tǒng)負(fù)載…
服務(wù)端調(diào)優(yōu)
Tomcat調(diào)優(yōu)
問(wèn)題1
服務(wù)調(diào)優(yōu)是在什么時(shí)間點(diǎn)介入調(diào)優(yōu)?
測(cè)試發(fā)現(xiàn)問(wèn)題:解決業(yè)務(wù)異常,也有一部分調(diào)優(yōu);而調(diào)優(yōu)更多的時(shí)候,是在上線以后介入調(diào)優(yōu)。
- Tomcat 服務(wù)器:是我們現(xiàn)在使用的內(nèi)置服務(wù)器,默認(rèn)的線程數(shù)?最大連接數(shù)?
問(wèn)題2
修改以上參數(shù)的大小,是否可以提升tomcat服務(wù)器性能?
答案:不考慮其他因數(shù)(硬件資源限制),改大tomcat最大線程數(shù)、最大連接數(shù)、等待隊(duì)列數(shù),理論上一定是可以提升服務(wù)器性能。
- Tomcat參數(shù)原理分析:
- 優(yōu)化配置:最大線程數(shù)提升4倍
問(wèn)題3
優(yōu)化后的TPS并沒(méi)有太大變化,是什么原因?
業(yè)務(wù)代碼沒(méi)有任何業(yè)務(wù)執(zhí)行,只執(zhí)行業(yè)主鍵查詢(xún),主鍵查詢(xún)是數(shù)據(jù)庫(kù)最快的查詢(xún)方式,耗時(shí)0-10ms,因此此操作不是一個(gè)耗時(shí)操作,不耗時(shí)不需要調(diào)優(yōu)
- 修改業(yè)務(wù)代碼,模擬耗時(shí)操作,然后重新打包部署
- tomcat配置沒(méi)有做優(yōu)化前的TPS:穩(wěn)定在 200 左右
- tomcat配置優(yōu)化后的TPS:可以發(fā)現(xiàn)TPS提升4倍,變成了800個(gè)TPS
KeepAlive
- 客戶端和服務(wù)器連接的時(shí)候,為了防止頻繁建立連接,釋放連接,浪費(fèi)資源,這樣會(huì)消耗資源造成性能下降。
- Jmeter使用長(zhǎng)連接進(jìn)行測(cè)試:
- 問(wèn)題:keep-alive 連接數(shù)是否是越多越好呢?
- 答案:keep-alive 連接本身消耗大量的資源,如果不能及時(shí)釋放,系統(tǒng)TPS就上不去,因此 keep-alive 連接數(shù)也必須要設(shè)置一個(gè)合理的連接數(shù)。
JVM調(diào)優(yōu)
為什么要進(jìn)行JVM調(diào)優(yōu)
問(wèn)題1:項(xiàng)目上線后,是什么原因促使必須進(jìn)行jvm調(diào)優(yōu)?
答案:調(diào)優(yōu)的目的就是提升服務(wù)性能
- JVM 堆內(nèi)存空間對(duì)象太多(Java線程、垃圾對(duì)象),導(dǎo)致內(nèi)存被占滿,程序跑不動(dòng)—性能?chē)?yán)重下降。
- 調(diào)優(yōu):及時(shí)釋放內(nèi)存
- 垃圾回收線程太多,頻繁回收垃圾(垃圾回收線程也會(huì)占用內(nèi)存資源,搶占cpu資源),必然會(huì)導(dǎo)致程序性能下降
- 調(diào)優(yōu):防止頻繁GC
- 垃圾回收導(dǎo)致 STW (stop the world)
- 調(diào)優(yōu):盡可能的減少 GC 次數(shù)
問(wèn)題2:JVM 調(diào)優(yōu)本質(zhì)是什么?
答案: JVM 調(diào)優(yōu)的本質(zhì)就是(對(duì)內(nèi)存的調(diào)優(yōu)) 及時(shí)回收垃圾對(duì)象,釋放內(nèi)存空間;讓程序性能得以提升,讓其他業(yè)務(wù)線程可以獲得更多內(nèi)存空間。
問(wèn)題3:是否可以把 JVM 內(nèi)存空設(shè)置的足夠大(無(wú)限大),是不是就不需要垃圾回收呢?
前提條件:內(nèi)存空間被裝滿了以后,才會(huì)觸發(fā)垃圾回收器來(lái)回收垃圾。
理論上是的,現(xiàn)實(shí)情況不行的!
尋址能力:(是否有這么大的空間)32位操作系統(tǒng) —— 4GB 內(nèi)存;64位操作系統(tǒng) —— 16384 PB 內(nèi)存空間
- 堆內(nèi)存空間大小的設(shè)置:必須設(shè)置一個(gè)合適的內(nèi)存空間,不能太大,也不能太小。
- 考慮到尋址速度的問(wèn)題,尋址一個(gè)對(duì)象消耗的時(shí)間比較長(zhǎng)的;一旦觸發(fā)垃圾回收,將會(huì)是一個(gè)災(zāi)難。(只能重啟服務(wù)器)。
調(diào)優(yōu)原則
- 原則一:GC 的時(shí)間足夠小:JVM 堆內(nèi)存設(shè)置足夠小。
- 垃圾回收時(shí)間足夠小,意味著 JVM 堆內(nèi)存空間設(shè)置小一些,這樣的話,垃圾對(duì)象尋址的時(shí)候消耗的時(shí)間就非常短,然后整個(gè)垃圾回收非常快速。
- 原則二:GC 的次數(shù)足夠少:JVM 堆內(nèi)存設(shè)置足夠大。
- GC 次數(shù)足夠少,JVM 堆內(nèi)存空間必須設(shè)置的足夠大,這樣垃圾回收觸發(fā)次數(shù)就會(huì)相應(yīng)減少。
- 原則一、原則二 是相互沖突的,因此需要權(quán)衡,內(nèi)存空間既不能設(shè)置太大,也不能設(shè)置太小。
- 原則三:發(fā)生 Full GC 周期足夠長(zhǎng):最好不發(fā)生 Full GC。
- MetaSpace 永久代空間設(shè)置大小合理,MetaSpace 一旦擴(kuò)容,就會(huì)發(fā)生 Full GC;
- 年代空間設(shè)置一個(gè)合理的大小,防止 Full GC;
- 盡量讓垃圾對(duì)象在年輕代被回收(90%);
- 盡量防止大對(duì)象的產(chǎn)生,一旦大對(duì)象多了以后,就可能發(fā)生 Full GC,甚至 OOM。
調(diào)優(yōu)原理
- 參考我的另一篇博文:https://blog.csdn.net/yangwei234/article/details/84778681
什么是垃圾?
- JVM調(diào)優(yōu)的本質(zhì):回收垃圾,及時(shí)釋放內(nèi)存空間,但是什么是垃圾?
- 在內(nèi)存中間中,那些沒(méi)有被引用的對(duì)象就是垃圾(高并發(fā)模式下,大量的請(qǐng)求在內(nèi)存空間中創(chuàng)建了大量的對(duì)象,這些對(duì)象并不會(huì)主動(dòng)消失,因此必須進(jìn)行垃圾回收,當(dāng)然 Java 垃圾回收不需要我們自己編寫(xiě)垃圾回收代碼,Java 提供各種垃圾回收器幫助回收垃圾,JVM垃圾回收是自動(dòng)進(jìn)行的)。
- 一個(gè)對(duì)象的引用消失了,這個(gè)對(duì)象就是垃圾,因此此對(duì)象就必須被垃圾回收器進(jìn)行回收,及時(shí)釋放內(nèi)存空間。
怎么找垃圾?
- JVM 提供了2種方式找到這個(gè)垃圾對(duì)象:引用計(jì)數(shù)算法、根可達(dá)算法(hotspot 垃圾回收器都是使用這個(gè)算法)。
- 引用計(jì)數(shù)算法:對(duì)每一個(gè)對(duì)象的引用數(shù)量進(jìn)行一個(gè)計(jì)數(shù),當(dāng)引用數(shù)為0時(shí),那么此對(duì)象就變成了一個(gè)垃圾對(duì)象。
- 不能解決循環(huán)引用的問(wèn)題,如果存在循環(huán)引用的話,無(wú)法發(fā)現(xiàn)垃圾。
- 根可達(dá)算法:根據(jù)根對(duì)象向下進(jìn)行遍歷,如果遍歷不到的對(duì)象就是垃圾。
如何清除垃圾?
- JVM提供了3種方式清除垃圾,分別是:
- mark-sweep:標(biāo)記-清除算法
- coping:復(fù)制算法
- mark-compact:標(biāo)記-整理(壓縮)算法
標(biāo)記-清除
- 該算法分為”標(biāo)記“和”清除“兩個(gè)階段:首先標(biāo)記所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有垃圾。
- 缺點(diǎn):效率不高,標(biāo)記和清除兩個(gè)過(guò)程的效率都不高;產(chǎn)生碎片,碎片太多會(huì)導(dǎo)致提前GC。
復(fù)制
- 該算法將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只是用其中的一塊,當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過(guò)的內(nèi)存空間一次清除掉(Young區(qū)就是使用的這種算法)。
- 優(yōu)缺點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效,但是空間利用率低。
標(biāo)記-整理
- 標(biāo)記過(guò)程仍然與”標(biāo)記-清除“算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端到邊界以外的內(nèi)存。
- 優(yōu)缺點(diǎn):沒(méi)有了內(nèi)存碎片,但是整理內(nèi)存比較耗時(shí)。
分代收集
- 在新生代中,每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活,那就選用復(fù)制算法;
- 而老年代中因?yàn)閷?duì)象存活率高、沒(méi)有額外空間對(duì)它進(jìn)行分配擔(dān)保,就必須使用”標(biāo)記-清除“或”標(biāo)記-整理“算法進(jìn)行收回。
垃圾回收器
- Java提供很多的垃圾回收器:10種垃圾回收器。
- 串行回收器:Serial、Serial old
- 并行回收器:ParNew、Parallel Scavenge、Parallel old
- 并發(fā)回收器:CMS、G1(分區(qū)算法)
特點(diǎn)
- Serial、Serial old、ParNew、Parallel Scavenge、Parallel old、CMS 都屬于物理分代垃圾收集器;年輕代、老年代分別使用不同的垃圾回收器。
- Serial、Serial old 是串行化的垃圾回收器。
- ParNew、CMS 組合是并行、并發(fā)的垃圾回收器。
- Parallel Scavenge、Parallel old 是并行的垃圾回收器
- G1是在邏輯上進(jìn)行分代的,因此在使用上非常方便,關(guān)于年輕代、老年代只需要使用一個(gè)垃圾回收器即可。
- ZGC是一款JDK 11中新加入的具有實(shí)驗(yàn)性質(zhì)的低延遲垃圾收集器。
- Shenandoah 是 OpenJDK 的垃圾回收器。
- Epsilon 是 Debug 使用的,調(diào)試環(huán)境下,驗(yàn)證 JVM 內(nèi)存參數(shù)設(shè)置的可行性。
常用垃圾回收器組合
- Serial + Serial old:是串行化的垃圾回收器,適合單核心的 CPU 的情況;
- ParNew + CMS:是響應(yīng)時(shí)間優(yōu)先組合;
- Parallel Scavenge + Parallel old:是吞吐量?jī)?yōu)先組合。
- G1:邏輯上分代的垃圾回收器組合。
垃圾回收器原理
Serial + Serial old
- Serial 是年輕代的垃圾回收器,單線程的垃圾回收器;Serial Old 是老年代的垃圾回收器,也是一個(gè)單線程的垃圾回收器,適合單核心的 CPU。
- 注意特點(diǎn):
- STW:當(dāng)進(jìn)行 GC 的時(shí)候,整個(gè)業(yè)務(wù)線程都會(huì)被停止,如果 STW 時(shí)間過(guò)長(zhǎng),或者 STW 發(fā)生次數(shù)過(guò)多,都會(huì)影響程序的性能。
- 垃圾回收器線程:多線程、單線程、并發(fā)、并行。
Parallel Scavenge + Parallel old
- 并行的垃圾回收器,是吞吐量?jī)?yōu)先的垃圾回收器組合,是JDK8默認(rèn)的垃圾回收器。
什么是并發(fā)、并行?
并發(fā):在一段時(shí)間內(nèi),多個(gè)線程搶占 CPU 的執(zhí)行,并發(fā)執(zhí)行,這些線程就叫并發(fā)線程。
并行:多個(gè)線程在同一時(shí)刻,在多個(gè) CPU 上同時(shí)執(zhí)行,這些線程叫做并行線程。
- PS + PO 回收垃圾的時(shí)候,采用的多線程模式回收垃圾。
- 注意特點(diǎn):
- STW:當(dāng)進(jìn)行 GC 的時(shí)候,整個(gè)業(yè)務(wù)線程都會(huì)被停止,如果 STW 時(shí)間過(guò)長(zhǎng),或者 STW 發(fā)生次數(shù)過(guò)多,都會(huì)影響程序的性能。
- 垃圾回收器線程:多線程、單線程、并發(fā)、并行。
ParNew + CMS
- ParNew 是并行垃圾回收器,年輕代的垃圾回收器;CMS 是并發(fā)垃圾回收器,回收老年代的垃圾。
- CMS 是響應(yīng)時(shí)間優(yōu)先的垃圾回收器,充分考慮了 STW 時(shí)間的問(wèn)題,減少 STW 的時(shí)間,延長(zhǎng)業(yè)務(wù)執(zhí)行時(shí)間。
- 注意:任何的垃圾回收器都無(wú)法避免 STW,因此 JVM 調(diào)優(yōu)實(shí)際上就是調(diào)整 STW 的時(shí)間。
G1
- 使用G1收集器時(shí),它將整個(gè)Java堆劃分成約2048個(gè)大小相同的獨(dú)立 Region 塊,每個(gè) Region 塊大小根據(jù)堆空間的實(shí)際大小而定,整體被控制 在1MB到32MB之間,且為2的N次冪,即1MB、2MB、4MB、8MB、16MB、32MB。可以通過(guò)-XX:G1HeapRegionsize設(shè)定。
- 所有的Region大小相同,且在JVM生命周期內(nèi)不會(huì)被改變。
內(nèi)存分代模型
- 通過(guò)內(nèi)存分代模型結(jié)構(gòu):大多數(shù)對(duì)象都會(huì)在年輕代被回收掉(90%+),很多對(duì)象都在15次的垃圾回收中被回收掉了,只有超過(guò)15次還沒(méi)被回收掉的才會(huì)進(jìn)入到老年代區(qū)域。
- 垃圾回收觸發(fā)的時(shí)機(jī):
- PS+PO:當(dāng)堆內(nèi)存被裝滿了,才會(huì)觸發(fā)垃圾回收(eden區(qū)域滿了,觸發(fā)了垃圾回收;old區(qū)域滿了,觸發(fā)垃圾回收)。
- CMS:JDK1.5 時(shí),當(dāng) eden 區(qū)域裝對(duì)象達(dá)到68%時(shí)候,就會(huì)觸發(fā)垃圾回收;JDK1.6+時(shí),92% 才會(huì)觸發(fā)垃圾回收器。
一個(gè)新對(duì)象被創(chuàng)建了,但是這個(gè)對(duì)象是一個(gè)大對(duì)象(查詢(xún)?nèi)?#xff09;,eden區(qū)域已經(jīng)放不下了,此時(shí)會(huì)發(fā)生什么?
JVM實(shí)戰(zhàn)調(diào)優(yōu)
- 明確 JVM 調(diào)優(yōu)的本質(zhì):GC-垃圾回收,及時(shí)釋放內(nèi)存空間;GC 次數(shù)要少,GC 時(shí)間少,防止 Full GC。進(jìn)行內(nèi)存參數(shù)設(shè)置。
典型參數(shù)設(shè)置
服務(wù)器硬件配置:4cpu、8GB 內(nèi)存 — jvm調(diào)優(yōu)內(nèi)存,考慮內(nèi)存。
- -Xmx4000m:設(shè)置 JVM 最大堆內(nèi)存(經(jīng)驗(yàn)值:3500m ~ 4000m,內(nèi)存設(shè)置大小,沒(méi)有一個(gè)固定的值,根據(jù)業(yè)務(wù)實(shí)際情況來(lái)進(jìn)行設(shè)置的,根據(jù)壓力測(cè)試、性能反饋情況,去做參數(shù)調(diào)試);
- -Xms4000m:設(shè)置 JVM 堆內(nèi)存初始化的值,一般情況下,初始化的值和最大堆內(nèi)存值必須一致,防止內(nèi)存抖動(dòng);
- -Xmn2g:設(shè)置年輕代內(nèi)存對(duì)象(eden、s1、s2);
- -Xss256k:設(shè)置線程棧大小,JDK 1.5+ 版本線程棧默認(rèn)是 1MB,相同的內(nèi)存情況下,線程堆棧越小,操作系統(tǒng)創(chuàng)建的線程越多。
- 再次進(jìn)行壓力測(cè)試:查看在此內(nèi)存設(shè)置模式下性能情況。
- 根據(jù)壓力測(cè)試結(jié)果,發(fā)現(xiàn)JVM參數(shù)設(shè)置,和之前沒(méi)有設(shè)置吞吐能力沒(méi)有太大的變化,因?yàn)闇y(cè)試樣本不足以造成 GC、Full GC 時(shí)間上的差異。
問(wèn)題:根據(jù)什么標(biāo)準(zhǔn)判斷參數(shù)設(shè)置是否合理呢?根據(jù)什么指標(biāo)進(jìn)行調(diào)優(yōu)呢?
- 發(fā)生幾次 GC、是否頻繁的發(fā)送GC?是否發(fā)生 Full GC、Full GC 發(fā)生是否合理?GC 的時(shí)間是否合理?OOM?
GC日志輸出
- 啟動(dòng)命令:
- 輸出GC日志的參數(shù)說(shuō)明:
- -XX:+PrintGCDetails 打印 GC 詳細(xì)信息
- -XX:+PrintGCTimeStamps 打印 GC 時(shí)間信息
- -XX:+PrintGCDateStamps 打印 GC 日期信息
- -XX:+PrintHeapAtGC 打印 GC 堆內(nèi)存信息
- -Xloggc:gc.log 把 GC信息輸出到 gc.log 文件中
- 執(zhí)行啟動(dòng)命令后,就會(huì)產(chǎn)生 GC 日志:
GC日志分析
- 可以使用 GCeasy進(jìn)行 GC日志分析:導(dǎo)入gc.log 進(jìn)行在線分析即可。
JVM內(nèi)存使用情況
關(guān)鍵指標(biāo)
- 總結(jié):可以發(fā)現(xiàn)業(yè)務(wù)線程執(zhí)行時(shí)間占比達(dá)到99%+,說(shuō)明 GC 時(shí)間在整個(gè)業(yè)務(wù)執(zhí)行期間所占用的時(shí)間非常少,幾乎不會(huì)影響程序性能;導(dǎo)致業(yè)務(wù)線程執(zhí)行時(shí)間占比高的原因是:
- 程序樣本數(shù)不夠;
- 程序運(yùn)行的時(shí)間不夠;
- 業(yè)務(wù)場(chǎng)景不符合要求(查詢(xún)沒(méi)有太多的對(duì)象數(shù)據(jù))
存在問(wèn)題
- 在一開(kāi)始就發(fā)生了FullGC:
- GC 詳細(xì)數(shù)據(jù)分析:
Full GC頻繁發(fā)生
- 查詢(xún) GC 內(nèi)存模型:jstat -gcutil PID 查詢(xún)此進(jìn)程的內(nèi)存模型
- Metaspace 永久代空間:默認(rèn)為 20 M(初始化大小),當(dāng) Metaspace 被占滿后,就會(huì)發(fā)生擴(kuò)容,一旦metaspace 發(fā)生一次擴(kuò)容,就會(huì)同時(shí)發(fā)送一次 Full GC。
- 啟動(dòng)命令:參數(shù)設(shè)置-XX:MetaspaceSize=256m
- 調(diào)整參數(shù)后,重啟項(xiàng)目,并進(jìn)行壓力測(cè)試,重新生成 GC 日志,并進(jìn)行分析
- 經(jīng)過(guò)參數(shù)調(diào)優(yōu)后,發(fā)現(xiàn) Full GC 已經(jīng)沒(méi)有發(fā)生了。
Young & Old 比例
- Sun公司推薦設(shè)置:整個(gè)堆的大小 = 年輕代 + 老年代 + 永久代(256m),推薦年輕代占整個(gè)堆內(nèi)存 3/8, 因此當(dāng)整個(gè)堆內(nèi)存設(shè)置大小為 2000m 時(shí),也就是說(shuō)年輕代大小應(yīng)該設(shè)置為 750m。
- 所以,定義年輕代 -Xmn750m,剩下的空間就是老年代空間。或者定義參數(shù) -XX:NewRatio=4,表示年輕代(eden、s0、s1)和老年代區(qū)域占比是 1:4。
- 年輕代大小、老年代大小比值可以根據(jù)業(yè)務(wù)實(shí)際情況設(shè)置比例,通過(guò)設(shè)置相應(yīng)的比例來(lái)減少相應(yīng) YoungGC、Full GC。
- 啟動(dòng)命令:修改參數(shù)-Xmn750m
- 調(diào)整參數(shù)后,重啟項(xiàng)目,并進(jìn)行壓力測(cè)試,重新生成 GC 日志,并進(jìn)行分析
- Young GC 增多了幾次,但是在 JVM調(diào)優(yōu)的原則中:要求盡量防止 Full GC 的發(fā)生,因此可以把 Full GC 設(shè)置的稍微大一些,意味著 Old 區(qū)域裝載對(duì)象很長(zhǎng)時(shí)間才能裝滿(或者永遠(yuǎn)都裝不滿),發(fā)生 Full GC 概率就非常小。
Eden & S0 & S1
- 官方給定設(shè)置:可以設(shè)置 eden、s 區(qū)域大小為 8:1:1,即 -XX:SurvivorRatio=8。
- 此調(diào)優(yōu)的原理:盡量讓對(duì)象在年輕代被回收,調(diào)大了eden區(qū)域的空間,讓更多對(duì)象進(jìn)入到 eden 區(qū)域,觸發(fā) GC 時(shí),更多的對(duì)象被回收。
- 啟動(dòng)命令:增加參數(shù)-XX:SurvivorRatio=8
- 調(diào)整參數(shù)后,重啟項(xiàng)目,并進(jìn)行壓力測(cè)試,重新生成 GC 日志,并進(jìn)行分析
- 發(fā)現(xiàn) Young GC 次數(shù)和時(shí)間有所減少和降低。
總結(jié)
- JVM 調(diào)優(yōu)(調(diào)整 JVM 內(nèi)存大小、比例),降低 GC 次數(shù),減少 GC 時(shí)間,從而提升服務(wù)性能。
- 調(diào)優(yōu)標(biāo)準(zhǔn):項(xiàng)目上線后,遇到問(wèn)題,調(diào)優(yōu)。
- GC 消耗時(shí)間:業(yè)務(wù)時(shí)間占比
- 頻繁發(fā)生 Full GC:調(diào)優(yōu) STW——程序暫停時(shí)間比較長(zhǎng),發(fā)生阻塞可能導(dǎo)致整個(gè)程序崩潰
- OOM:調(diào)優(yōu)
GC組合
吞吐量?jī)?yōu)先
- 并行的垃圾回收器:Parallel Scavenge(年輕代) + Parallel Old(老年代) ---- 是JDK默認(rèn)的垃圾回收器。
- 顯式的配置PS+PO垃圾回收器:-XX:+UseParallelGC -XX:+UseParallelOldGC。
響應(yīng)時(shí)間優(yōu)先
- 并行垃圾回收器(年輕代),并發(fā)垃圾回收器(老年代) :ParNew + CMS (響應(yīng)時(shí)間優(yōu)先垃圾回收器)。
- 顯式配置:ParNew + CMS 垃圾回收器組合:-XX:+UseParNewGC -XX:+UseConcMarkSweepGC。
- CMS 只有在發(fā)生 Full GC 時(shí)才起到作用,CMS一般情況下不會(huì)發(fā)生,因此在 JVM 調(diào)優(yōu)原則中表示盡量防止發(fā)生 FullGC,因此 CMS 在 JDK14 已經(jīng)被廢棄。
G1
- G1 垃圾回收器是邏輯上分代模型,使用配置簡(jiǎn)單。
- 顯式配置:-XX:+UseG1GC
- 調(diào)整參數(shù)后,重啟項(xiàng)目,并進(jìn)行壓力測(cè)試,重新生成 GC 日志,并進(jìn)行分析
- 經(jīng)過(guò)測(cè)試,發(fā)現(xiàn) G1 GC 次數(shù)減少了,但是 GC 總時(shí)長(zhǎng)增加很多;時(shí)間增加,意味著服務(wù)性能就沒(méi)有提升上去。
總結(jié)
以上是生活随笔為你收集整理的压力测试与服务端调优(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 大数据笔试真题集锦---第十一章:Sqo
- 下一篇: mysql-8.0.27-winx64