一、安裝Jmeter
下載地址:http://jmeter.apache.org/download_jmeter.cgi
下載后直接進入bin目錄,直接運行jmeter即可,我這里用得是mac,直接sh jmeter
1、調整語言
Options--Choose Languages--Chinese(Simple lified)
2、添加jmeter-plugin插件
下載地址:鏈接: https://pan.baidu.com/s/1RXD6JnT5LJx5mBvxmUf7JQ 提取碼: 90ni
下載后文件為plugins-manager.jar格式,將其放入jmeter安裝目錄下的lib/ext目錄,然后重啟jmeter,即可。
3、添加jpgc插件
這個插件可以監測TPS,RT等重要指標。
選項-plugin Manager --jpgc - Standard Set,安裝后重啟。
二、壓測
寫一個簡單的demo
@RequestMapping(value = "/goods/detail/nocache/{seckillId}",method = RequestMethod.GET) public TbSeckillGoods findOneNoCache(@PathVariable Integer seckillId){ TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(id); }
運行:
nohup java -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
這就是一個最簡單的使用主鍵查詢。
1、添加測試項(01-秒殺系統測試方案)
測試方案--添加--線程(用戶)--線程組,設置測試接口名稱(01-商品詳情測試方案)。
測試接口--添加--取樣器--HTTP請求(01-商品詳情HTTP請求)
測試接口--添加--監聽器--聚合報告(02-商品詳情聚合報告)
測試接口--添加--監聽器--查看結果樹(03-商品詳情結果樹)
測試接口--添加--監聽器--jp@gc - Transactions per Second (04-商品詳情接口TPS)
測試接口--添加--監聽器--jp@gc - Response Times Over Time(05-商品詳情響應時間)
2、驗證
點擊開始,然后查看結果樹中的響應數據,可以看到正常返回,驗證無誤。
3、正式壓測
修改測試方案中的線程數和循環次數,這里模擬20W個樣本,線程數為4000,啟動時間為5秒,循環次數為50次,這幾個參數的意思是:在5秒內順序啟動4000個線程,這個操作循環50次。這50次循環是並行執行的。
(1)TPS
如果服務的TPS存在明顯的抖動,說明要么服務有問題,要么網絡有問題。TPS性能曲線不能出現明顯抖動(當前條件當測試演變比較穩定),查看服務問題。
這里再說明一下TPS和QPS,TPS ,QPS,吞吐量:大多數情況下,單獨一個接口: TPS = QPS = 吞吐量(每秒請求數)
(2)RT
(3)聚合報告
# 樣本: 測試的樣本數 20w
# 平均值: 所有的請求從發送請求到請求結束所消耗的平均時間
# 中位數:50%的請求在713ms之內響應結束
# 90%百分位:90%的請求在782ms之內響應結束
# 最小值: 請求消耗的最小時間
(4)測試參數
三、服務端調優
1、分析與調優
查看線程數:pstree -p 進程號 | wc -l
pstree -p 3769 | wc -l
如果沒有命令,需要安裝pstree:
yum -y install psmisc
經過測試,發現服務器只產生了 200 個線程來處理業務請求,增加線程數,可以提升吞吐能力;考慮 cpu 處理能力的問題,cpu 上下文切換耗時,搶占 cpu 等待問題;考慮 cpu 性能損耗問題,使用 top 查看即可;
Springboot內置的Tomcat配置信息在:spring-boot-autoconfigure-2.2.5.RELEASE.jar中的spring-configuration-metadata.json中
其中比較重要的三個配置項:最大連接數、服務隊列、最大線程數,三者的關系如下圖所示:
首先使用等待隊列接收請求,然后創建連接,然后執行業務,如果當最大連接數,等待隊列都已經滿了,tomcat 服務就會拒絕連接。
(1)最大連接數:
(2)服務隊列
(3)最大線程數
由於部署應用的服務器是4C8G,單個線程默認為200個線程,這里4個CPU,將線程數調整為800。
server: port: 9000 tomcat: # 編碼格式 uri-encoding: utf-8 # 服務隊列 accept-count: 1000 # 最大連接數 max-connections: 20000 # 最大線程數 max-threads: 800 # 初始化線程,應對突發流量 min-spare-threads: 10
2、驗證壓測
經過 20w 個樣本的測試,發現 TPS 沒有發生任何的變化,TPS = 2700
可以發現在服務器最大線程數增加了 4 倍,理論上來說,TPS 一定會增加 4 倍,但是根據實際測試結果,發現 TPS 沒有任何的變化,這是因為沒有執行任何業務,不是一個耗時的操作,主鍵查詢:0-10ms 結束,無需要對一個不耗時操作進行調優。
結論:調優應該是對於耗時操作進行調優。
3、模擬耗時操作調優
模擬一個耗時操作
public TbSeckillGoods findOne(Integer id){ //直接從數據庫查詢 //主鍵查詢 : cpu不耗時操作 TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(id); //計算對象大小 //模擬程序耗時操作,如果方法是一個筆記耗時的操作,性能優化非常有必要的!! try { Thread.sleep(1000); LOGGER.info("模擬耗時操作,睡眠1s時間!"); LOGGER.info("對象占用jvm堆內存大小: {}", RamUsageEstimator.humanSizeOf(seckillGoods)); } catch (InterruptedException e) { e.printStackTrace(); } //返回結果 return seckillGoods; }
在未調優的情況下進行壓測:沒有優化之前,對於一個耗時操作來說,TPS = 200
調優后壓測:調優之后的 TPS 情況(線程數增加:800) -- 理論上: cpu 沒有任何壓力,TPS 應該會獲得倍數的提升,提升 4 倍
經過測試:發現 TPS 有了 4 倍的提升,tps = 800
4、Keepalive
客戶端和服務端連接的時候,為了防止頻繁建立連接,釋放連接,浪費資源,這樣就好損耗的性能,造成性能嚴重下降;
可以發現: jmeter connection : keep -alive 長連接
查看連接數:
netstat -anp | grep ESTABLISHED | wc -l
但是keepalive 長連接本身也會消耗大量資源,如果這些長連接不能及時釋放,長連接將會占用大量資源,系統 TPS 就會上不去;因此對 keepalive 設置一個比較合理的連接數;另外: 長連接也必須及時釋放,沒有請求使用這個鏈接,這個鏈接一段時間必須釋放;
可以在代碼中定制tomcat服務器的長鏈接設置。
@Component public class WebServerConfig implements WebServerFactoryCustomizer<ConfigurableWebServerFactory>{ // 定制tomcat服務器 @Override public void customize(ConfigurableWebServerFactory configurableWebServerFactory) { ((TomcatServletWebServerFactory)configurableWebServerFactory).addConnectorCustomizers(new TomcatConnectorCustomizer() { // 獲取tomcat連接器 @Override public void customize(Connector connector) { // 獲取protocol Http11NioProtocol protocolHandler = (Http11NioProtocol) connector.getProtocolHandler(); // 如果keepalive連接30s,還沒有人使用,釋放此鏈接 protocolHandler.setKeepAliveTimeout(30000); // 允許開啟最大長連接數量,4cpu,8gb protocolHandler.setMaxKeepAliveRequests(10000); } }); } }
四、線上問題分析
(一)問題分類
發現問題,解決問題 (測試時候發現一些問題,修復,調試,調優 , 更多的時候: 上線以后發現一些問題,解決問題)系統出現問題分類:
1、系統異常
CPU 占用率過高,磁盤滿了,磁盤 IO 阻塞,網絡流量異常等等問題
排查指令:TOP,free,dstat , pstack , vmstat , strace 獲取異常信息,排查系統異常
2、業務異常
流量太大系統扛不住,耗時長,線程死鎖,並發問題,頻繁 full gc ,oom 等等
排查: top, jstack ,pstack , strack 日志
(二)問題排查
1、TOP命令
Top 指令監控 cpu 使用情況,根據 cpu 使用分析系統整體運行情況
關注性能指標: load average : 1 分鍾之內 cpu 平均使用率,5 分鍾之內 cpu 平均使用率,15分鍾之內 cpu 平均使用率;如果1分鍾之內cpu使用率較高,但是5分鍾或15分鍾內較低,有可能是短暫的流量激增導致,可以暫時不用關心。
單核心 cpu:
1)load average < 1 , 表示 cpu 毫無壓力,比較空閑,運行流暢
2)load average = 1 , 表示 cpu 剛剛被占滿,沒有可供提供的 cpu 資源
3)load average > 1 , 表示 cpu 已經滿負荷運作,線程處於阻塞等待狀態,等待 cpu資源
4)load average > 5 , 表示 cpu 已經處於超負荷運作,線程已經大面積阻塞,必須進行優化處理;
4 核心 cpu:
1)load average < 4 , 表示 cpu 毫無壓力,比較空閑,運行流暢
2)load average = 4 , 表示 cpu 剛剛被占滿,沒有可供提供的 cpu 資源
3)load average > 4 , 表示 cpu 已經滿負荷運作,線程處於阻塞等待狀態,等待 cpu資源
4)load average > 10 , 表示 cpu 已經處於超負荷運作,線程已經大面積阻塞,必須進行優化處理;
2、Free命令
Free 排查線程問題:內存問題很多時候引起 cpu 較高的原因。
3、磁盤
Df 指令查看磁盤問題,查看磁盤使用情況,有時候服務出現問題,其實就是磁盤出現問題。
4、網絡
Dstat 命令: 集成 vmstat , iostat , netstat ,工具完成任務,-c 查看 cpu 使用情況, -d 查看磁盤讀寫,-n 網絡狀態 -l 顯示系統負載
詳細的參數展示可以參考下這篇文章:http://www.yishimei.cn/network/850.html
五、JVM調優概述
(一)為什么調優
1、調優的目的
調優的目的就是為了提升項目性能,避免項目出現一些不可預知的 bug(頻繁 fullgc,oom);
(1)jvm 堆內存空間對象太多(Java 線程,垃圾對象),導致內存空間被占滿,程序跑不動 –性能嚴重下降,通過調優:及時釋放內存空間
(2)垃圾回收線程太多(頻繁的垃圾回收,垃圾回收線程也會占用 CPU,內存資源),必然導致程序性能下降,通過調優:防止頻繁的 gc
(3)垃圾回收導致 STW (stop the world : 停止整個世界 --- 整個業務執行全部暫停),通過調優:盡可能減少 gc 次數
2、JVM 調優的本質
jvm 調優本質就是(對內存空間的調優)及時是否垃圾對象占用的內存空間,讓程序性能得以提升,讓其他業務線程可以使用內存空間;
3、如果把 jvm 堆內存設置的足夠大(無限大),是不是不需要垃圾回收?
理論上確實可以考慮內存空間垂直擴容,解決 JVM 內存問題,但是同樣存在問題:
(1)成本問題 --- 高性能服務器
(2)一旦觸發垃圾回收 --- gc 時間比較長
(3)微服務架構場景下(每一個服務都是一個微小,獨立的服務) --- 水平擴展
(4)尋址能力的問題(JVM 默認內存調優分配空間: 32GB,超過32G就不會進行調優):
32 位操作系統: 2~32 = 4GB 內存空間 --- Java 對象 8 字節 指針壓縮 : 4GB *8 = 32GB
64 位操作系統 2~64 = 16384PB
小結: JVM 內存空間設置,必須設置一個大小合適的內存空間,不能太大,也不能設置太小;
(1)成本問題 --- 高性能服務器
(2)一旦觸發垃圾回收 --- gc 時間比較長
(3)微服務架構場景下(每一個服務都是一個微小,獨立的服務) --- 水平擴展
(二)JVM 調優原則
1、gc 時間足夠小(堆內存設置足夠小)
此原則就是讓我們在設置堆內存空間時候,不要把內存空間設置的太多,防止 gc 消耗太多的時間;
2、gc 的次數足夠少(堆內存空間設置的足夠大)
GC 觸發條件: 內存空間被占滿,立即觸發垃圾回收(ps,po),也就是說內存空間被占滿一次,就發生一次 gc,占滿多次就發生多次 gc;
3、發生 fullgc 周期足夠長(最好不要發生 fullgc)
(1)metaspace 元數據空間大小設置合適 ,metaspace 一旦發生擴容,fullgc 就會發生
(2)老年代空間設置一個合理的大小,防止 fullgc
(3)盡量讓垃圾對象在年輕代回收(90%)
(4)盡量防止大對象的產生,一旦大對象多了以后,就可能發生 fullgc , 甚至 OOM
(三)JVM 調優原理
1、JVM 調優本質:
回收垃圾,及時釋放內存空間。在 Java 堆內存中,那些沒有被引用的對象就是垃圾(高並發模式下,大量的請求在內存空間中創建了大量的對象,這些對象不會主動消失,必須進行垃圾回收,當然 Java 語言自己提供了垃圾回收器,幫助我們回收垃圾,JVM 垃圾是自動進回收的)
JVM 提供 2 種方法尋找垃圾:引用計數法和根可達算法
2、垃圾清理算法:
mark-sweep 標記清除算法、copying 拷貝算法、mark-compact 標記壓縮算法。
標記清除算法:
過程:(1)使用根可達算法找到垃圾對象,對垃圾對象進行標記(僅僅是做一個標記);(2)對標記的對象做清除。
優點: 簡單,高效;
缺點: 產生很多的內存碎片
copying 算法 – 一開始把內存空間一分為二,分為 2 份大小相同的內存空間,一般內存空間作為備份使用。
過程:(1)選擇(尋址)存活對象;(2)把存活對象拷貝另一半空閑空間中,且是連續的空間;(3)把存活對象拷貝結束后,另一半空間中就是垃圾對象(全是垃圾對象),直接清除即可;
優點:簡單,內存空間是連續的,不會存在內存碎片
缺點:內存空間的浪費
mark-compact 標記壓縮算法:
過程:(1)標記垃圾(只標記,不清除);(2)再次掃描內存空間(未被標記的對象就是存活對象),找到存活對象,且把存活對象向一端移動(一端內存空間是連續的)--壓縮,整理;(3)當存活對象全部被移動到一端后,另一端就是垃圾對象,直接清除即可
3、垃圾回收器
Java 語言提供了 10 種垃圾回收器:
特點:
(1)Serial(年輕代) Serial Old(老年代) , parNew(年輕代) CMS(老年代) , Parallel Scavenge(年輕代) Parallel Old(老年代) 都屬於物理分代模型中垃圾回收器,年輕代,老年代模型,分別都使用不同的垃圾回收器;
(2)G1 在邏輯上分代模型,使用非常方便;關於年輕代,老年代只需要使用 g1 一個垃圾回收器即可;
(3)zgc zgc 是 jdk11 新加入的垃圾回收器,在試驗階段;
(4)shenandoah openJDK 的垃圾回收器
(5)epsilon 是 debug 使用的,在調試環境下,驗證 jvm 內存參數設置的可行性;
(6)Serial 和 Serial Old 串行化的垃圾回收器
(7)parNew和CMS : 響應時間優先垃圾回收器組合 (fullgc 比較多,無法避免 --- cms)
(8)parallel scavenge 和 parallel old : 吞吐量優先的垃圾回收器組合
常用垃圾回收器組合:
(1)Serail + Serial Old : 串行化的垃圾回收器,適合單核心的 cpu 服務器
(2)parNew + CMS : 響應時間有些的垃圾回收器,並行,並發垃圾
(3)Parallel Scavenge+Parallel Old : 並行垃圾回收器
(4)g1 邏輯上分代垃圾回收器
4、垃圾回收器原理
(1)Serial+Serial Old
Serial : 年輕代垃圾回收器,單線程垃圾回收器; Serial Old : 老年代的垃圾回收器,也是一個單線程的垃圾回收器,適合單核心 cpu 情況。
注意:1、stw : 任何垃圾回收器都無法避免 stw(stop the world : 當進行 gc 的時候,整個業務線程必須暫停),如果 stw 時間過長,或者 stw 發生次數過多,都會影響程序的性能;2、垃圾回收線程: 多線程,單線程,並發,並行
(2)Parallel Scavenge + Parallel Old
Parallel Scavenge+Parallel Old : 並行垃圾回收器,吞吐量優先的垃圾回收器組合,是 JDK8 默認垃圾回收器組合;(並行: 同一個時候,同時執行,並行;並發: 在一段時間內,多個線程搶占式交叉執行,叫做並發模式;)
PS + PO : 垃圾回收器進行垃圾回收器的時候,采用多線程模式回收垃圾
(3)parNew+CMS
parNew : 年輕代垃圾回收器,並行的垃圾回收器;
CMS : 並發垃圾回收器,響應時間優先垃圾回收器
初始化標記:(尋址垃圾比較耗時)只標記跟根對象相關聯的對象,因此耗時比較少,且采用單線程模式標記
並發標記: (尋址垃圾比較耗時)為了防止 gc 時候 stw, 因此使用並發模式標記垃圾,也就是說讓業務線程和 gc 標記線程交叉執行;
重新標記: 重新標記漏標的對象,此時漏標對象比較少,因此耗時比較少
並發清理:(清理垃圾比較耗時) 采用並發模式清理垃圾,業務線程和清理垃圾線程交叉執行,以此減少業務線程停頓的時間;
(4)G1
G1 jdk11 成為了默認的垃圾回收器;采用了分區的思想;對內存進行邏輯上分代;采用RememberSet 集合記錄每一個 region 區域
5、內存分代模型
通過內存分代模型: 大多數對象都會在年輕代被回收(90%+),超過 15 次沒有被回收的對象就進入 old 區域。垃圾回收器觸發時機:
(1)ps + po : 當內存空間(eden,old)被占滿后,觸發垃圾回收器
(2)cms 垃圾回收器
jdk1.5 : 68% ,當 eden 區域被裝載到 68%的時候,觸發垃圾回收器
jdk1.6+ : 92% 觸發垃圾回收器
六、JVM調優實戰
(一)調優實戰
JVM 調優的本質就是 GC(垃圾回收,及時釋放掉內存,提供給其他的線程使用—並發模式),每次 GC 的時候,導致業務線程 STW, 因此必須進行綜合的考量:頻繁的 gc 也會導致性能下降
JVM 調優其實就是選擇一個合適的垃圾回收器(在不同的場景下),設置一些合理垃圾回收參數(參考 JVM 內存模型),分配合理的內存(gc 時間少,次數少,jvm 內存既不能太大,也不能太小)。因此調優的實踐本質就是設置 jvm 參數
1、典型設置
典型的參數設置: 服務器配置 —> 4cpus,8GB
1、-Xmx4000m 設置 JVM 堆內存最大值(經驗值設置:3500m --- 4000m,內存大小的設置,沒有一個固定值,根據業務場景實際情況,根據壓力測試運行情況進行調試,在上線后,進行調試)。例如: 對象 1 占用內存 128KB;對象 2 占用內存 300KB
2、-Xms4000m 設置 JVM 初始化內存(必須和 Xmx 最大內存設置一致,防止內存抖動,損耗性能)
3、-Xmn2g 設置年輕代大小(eden ,s0 ,s1)
4、-Xss256k 設置線程堆棧大小,jdk1.5+版本線程堆棧默認 1MB, 相同內存情況下,線程堆棧越小,操作系統有能力創建更多線程,系統性能將會越好;
查看對象占用JVM堆內存大小:
RamUsageEstimator.humanSizeOf(seckillGoods)
然后調整代碼的執行命令,設置上面的參數:
nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
根據壓力測試結果(20w 樣本),發現 JVM 內存參數設置后,沒有任何優化效果(變化),原因就在於在這個業務場景下沒有發生頻繁的 gc(gc 導致 stw ,stw 最終影響性能);那我們是根據什么指標判斷 jvm 調優的參數是合適的,是否能提到調優的效果的呢:
(1)發生幾次 GC ,GC 次數是否減少,是否頻繁的發生 GC, 發送 GC 時間
(2)業務線程執行時間比例 (業務線程執行時間超過 95%, 5%時間 gc 時間,此時不需要調優)
(3)是否發生 fullgc (fullgc 耗時比較長,性能影響比較大,fullgc 發生次數)
(4)oom
2、GC日志
JVM 在 gc 的時候輸出日志,把日志寫入文件中,使用相應工具(gceasy.io)對日志進行分析,分析 jvm 堆內存調優的結果是否合適。
nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
通過 jvm 相關參數,輸出 gc 日志,通過分析 gc 日志判定 gc 的參數設置是否合理;從而給調試 jvm 堆內存設置提供參考依據;
拿到 gc 日志后,可以在 gceasy.io 網站進行在線分析
(1)內存使用情況
用於展示各分代的總內存和最大使用內存。
(2)執行時間對比
這個是關鍵的是否需要JVM調優的判斷標准,如果業務時間占比大於95%,就無需調優。
(3)GC耗時占比
(4)發生GC的時間點和次數
根據內存分布情況,old 最大使用 157mb , 而在此時卻發生了 fullgc ,很明顯這是不正常的,必須進行調試,規避不正常的 fullgc
(5)GC統計
3、fullGC問題
20w 樣本測試后,old 區域使用最大值 157mb, old 區域分配的內存是 1.9gb , 卻發生了 full gc,這肯定不正常的,原因: metaspaceSize 雲數據空間發生了擴展,導致了 fullgc 的發發生;metaspace 發生一次擴容,就會發生一次 fullgc(可以查看gc日志,可以看到元空間占用內存在變大)
jstat -gcutil 11811 jstat -gc 11811 2s 3 java -XX:+PrintFlagsFinal -version | grep MetaspaceSize
根據 metaspace 擴容閥值的大小,看出超過 20m,就會發生第一次擴容(gc日志);
Metaspace 發生了擴容(gc日志):
解決方案: 觀察 gc 日志,看 metaspace 最大使用空間是多少,然后把 metaspace 空間大小設置為比這個值大即可;
根 據 上 圖 所 示 , metaspace>55.11mb ; metaspace = 256m , 完 全 夠 用 的 ;-XX:MaxMetaspaceSize=500m :定義最大的元數據空間,此時如果 metaspace 裝不下,就會發生 fullgc ,同時 oom;
nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
查看日志優化情況,看 fullgc 是否發生:
可以發現此時 fullgc 消失了,說明解決問題:
4、Yong&old
年輕代,老年代大小比例的設置根據業務情況進行靈活的設置,無非就是 yong 空間設置大些,盡量讓對象在年輕被回收;或者是老年代設置大些,在一些大對象,老年代對象比較多的情況下;
設置方案: -XX:NewRatio = 4 ,年輕代 : 老年代比值 = 1:4,預測結果: 年輕代空間進一步縮小(更頻繁的 yong gc – 耗時少),老年代的空間進一步增大(盡量防止 fullgc 的發生 – 不耗時)
分配結果: 1、yong : old = 1:4 (4000MB) 800MB:3200MB , yong memory 變得更小了,oldmemory 變得更大了;2、-Xmn2g 直接設置年輕代大小,剩下的就是老年代的;
修改配置:將Xmn刪除(-Xmn2g),新增NewRatio配置項(-XX:NewRatio=4)
nohup java -Xmx4000m -Xms4000m -XX:NewRatio=4 -Xss256k -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
Yong gc 發生的次數更多了,但是 gc 時間更加快速了,但是總消耗的時間變多了;
但是這種也不是不能這樣設置,這是一個需要權衡的結果,使用場景: 防止發生 fullgc(fullgc 有一些,消耗時間)
5、Eden & s0 & s1
盡量讓對象在年輕代被回收(大多數對象都在年輕代被釋放內存)官方推薦設置: eden : s0 : s1 = 8:1:1 設置方式: -XX:SurvivorRatio = 8。
(二)垃圾回收器組合
1、吞吐量優先
並行垃圾回收器:
年輕代: parNew , Parallel Scavenge
老年代: Parallel old
對於吞吐量優先的垃圾回收器: 使用常用組合: ps + po ,此組合是 jdk1.8 默認的垃圾回收器
nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
2、響應時間優先
響應時間優先組合: parNew + CMS 垃圾回收器 ,響應時間優先主要是對 CMS(老年代垃圾回收器)來說的,適用於:老年代發生 fullgc 比較多的情況,且無法避免 fullgc;
-XX:+UseParNewGC : 年輕代垃圾回收器,並行的垃圾回收器
-XX:+UseConcMarkSweepGC: 老年代的垃圾回收器,並發的垃圾回收器(業務線程交叉執行)
nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
3、G1 組合
XX:+UseG1GC : 表示使用 g1 垃圾回收器; 使用更加簡單,邏輯上分代模型;
nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &
可以發現: 垃圾回收次數比較少的,但是總耗時比較長;