JVM 中 GC 调优的主要思路是避免 FullGC,同时选择合适的垃圾回收器, 减少 STW 的时间,
确保用户的整体体验。
秒杀接口服务器, 配置为 4 核 8G
压测服务器,配置为4核8G
Ab(ApacheBench)测试工具是Apache提供的一款测试工具,具有简单易上手的特点,在测试Web服务时非常实用。
ab一般都是在Linux上用。
安装非常简单,只需要在Linux系统中输入yum-yinstallhttpd-tools命令,就可以了。安装成功后,输入ab命令,可以看到以下信息:
ab工具用来测试postget接口请求非常便捷,可以通过参数指定请求数、并发数、请求参数等
测试get请求接口
ab-c10-n100http://www.test.api.com/test/login?userName=test&password=test
测试post请求接口
ab-n100-c10-p’post.txt’-T’application/x-www-form-urlencoded’ ‘http://test.api.com/test/register’
post.txt为存放post参数的文档,存储格式如usernanme=test&password=test&sex=1
参数的含义:
-n:总请求次数(最小默认为1);
-c:并发次数(最小默认为1且不能大于总请求次数,例如:10个请求,10个并发,实际就是1人请求1次);
-p:post参数文档路径(-p和-T参数要配合使用);
-T:header头内容类型(此处切记是大写英文字母T);
输出中,性能指标参考
Requestspersecond:吞吐率,指某个并发用户数下单位时间内处理的请求数;
Timeperrequest:上面的是用户平均请求等待时间,指处理完成所有请求数所花费的时间/(总请求数/并发用户数);
Timeperrequest:下面的是服务器平均请求处理时间,指处理完成所有请求数所花费的时间/总请求数;
Percentageoftherequestsservedwithinacertaintime:每秒请求时间分布情况,指在整个请求中,每个请求的时间长度的分布情况,例如有50%的请求响应在8ms内,66%的请求响应在10ms内,说明有16%的请求在8ms~10ms之间。
后台启动秒杀接口
nohup java -jar mall-web-order.jar –spring.profiles.active=beta –eureka.instance.ip-address=106.52.62.38&
直到Eureka注册成功
对秒杀服务进行压力测试,模拟以下并发用户数下的服务的响应情况:
200个并发用户/20万请求量(总)
压测准备(需要准备seesion信息):
ab-n 200000 -c 200 -p ‘post.txt’ -T ‘application/x-www-form-urlencoded’
‘http://94.191.83.120:8186/mall/api/killgoodsSpec/kill’
在压测目录下创建一个post.txt,保存一下信息
killId=25
JSESSIONID=6308426a-60dd-43e3-af0e-73364df5a2e0
还有一句话,无监控不调优,所以我们需要监控起来。JVM中我们使用jstat命令监控一下JVM的GC情况。
统计GC的情况。
jstat- gc 7131 5000 50 |awk ‘{print$13,$14,$15,$16,$17}’
在默认不配置JVM堆内存大小的情况下,JVM根据默认值来配置当前内存大小。我们可以通过以下命令来查看堆内存配置的默认值:
java-XX:+PrintFlagsFinal-version|grepHeapSize
这台机器上启动的JVM默认最大堆内存为2048MB,初始化大小为128MB。
1、200个并发用户/20万请求量(第一次)
压测前的GC情况
YGC YGCT FGC FGCT GCT
22 0.273 4 0.551 0.824
使用AB进行压力测试:
ab -n 200000 -c 200 -p ‘post.txt’ -T ‘application/x-www-form-urlencoded’ http://dwfapi.goldwind.com.cn:8280/services/rest/authentication/1.0.0/
统计GC情况
jstat- gc 9656 5000 20 |awk ‘{print$13,$14,$15,$16,$17}’
YGC YGCT FGC FGCT GCT
52 1.178 4 0.551 1.729
结果 30次YGC0.9s
2、200个并发用户/20万请求量(第二次)
使用AB进行压力测试:
ab -n 200000 -c 200 -p ‘post.txt’-T’application/x-www-form-urlencoded’ ‘http://106.55.152.41:8186/mall/api/killgoodsSpec/kill’
统计GC情况
jstat -gc 9656 2000 50 |awk ‘{print$13,$14,$15,$16,$17}’
YGC YGCT FGC FGCT GCT
88 2.372 5 1.165 3.537
结果:
36次YGC1.2s
1次FGC0.6s
GC频率
过多的YGC会给系统带来压力,STW的时间达到了1.2s
FullGC带来很大的问题,FullGC一般在生产服务器上会放大,一般至少10倍及以上(因为这个项目只是压测秒杀接口,真实服务器上还有其他的接口在访问,也在产生对象,对于FGC的影响更大)
1、调整新生代、老年代的大小
2、选择垃圾回收器
调优方案
堆空间不变2G,新生代1.5G,初始值和最大值一样。采用CMS垃圾回收器
nohup java -jar -XX:+UseConcMarkSweepGC -Xms2000m -Xmx2000m -Xmn1500m
mall-web-order.jar –spring.profiles.active=beta
–eureka.instance.ip-address=106.52.62.38&
1、200个并发用户/20万请求量(第一次)
使用AB进行压力测试:
ab -n 200000 -c 200 -p ‘post.txt’ -T ‘application/x-www-form-urlencoded’ ‘http://106.52.62.38:8186/mall/api/killgoodsSpec/kill’
YGC YGCT FGC FGCT GCT
压测前 7 0.310 4 0.326 0.636
压测后 17 0.880 4 0.326 1.206
结果
10次YGC 0.57s
YGC次数减少,YGC总耗时减少
2、200个并发用户/20万请求量(第二次)
使用AB进行压力测试:
ab -n 200000 -c 200 -p ‘post.txt’ -T ‘application/x-www-form-urlencoded’
‘http://106.52.62.38:8186/mall/api/killgoodsSpec/kill’
统计GC情况
YGC YGCT FGC FGCT GCT
压测前 7 0.310 4 0.326 0.636
压测一次后 17 0.880 4 0.326 1.206
压测二次后 26 1.527 4 0.326 1.852
结果
9次YGC 0.64s
成功避免FullGC
调优方案
nohup java -jar -XX:+UseG1GC -Xms2000m -Xmx2000m mall-web-order.jar –spring.profiles.active=beta –eureka.instance.ip-address=106.55.152.41&
1、200个并发用户/20万请求量(第一次)
统计GC情况
YGC YGCT FGC FGCT GCT
压测前 12 0.320 0 0.000 0.320
压测一次后 22 0.850 0 0.000 0.850
结果
10次YGC0.53s
2、200个并发用户/20万请求量(第二次)
使用AB进行压力测试:
ab -n 200000 -c 200 -p ‘post.txt’ -T ‘application/x-www-form-urlencoded’
‘http://106.52.62.38:8186/mall/api/killgoodsSpec/kill’
统计GC情况
YGC YGCT FGC FGCT GCT
压测前 12 0.320 0 0.000 0.320
压测一次后 22 0.850 0 0.000 0.850
压测二次后 31 1.671 0 0.000 1.671
结果
9次YGC 0.82s
完全避免FGC,但是YGC对比CMS总体STW要长(一般压测第一次是预热,第二次可以算做标准的结果),这个是因为G1采用化整为零的处理方式,也是需要付出一定的代价的。
(实战验证理论)
GC频率
高频的FullGC会给系统带来非常大的性能消耗,虽然MinorGC相对FullGC来说好了许多,但过多的MinorGC仍会给系统带来压力。
内存
这里的内存指的是堆内存大小,堆内存又分为年轻代内存和老年代内存。堆内存不足,会增加MinorGC,影响系统性能。
一般推荐对于追求性能的服务,比如秒杀等服务,内存一定最好给足(-Xms和-Xmx设置成一样大),一来避免拓展空间的FGC,二来避免OOM。
吞吐量
频繁的GC将会引起线程的上下文切换,增加系统的性能开销,从而影响每次处理的线程请求,最终导致系统的吞吐量下降。
所以综合上述,一般来说PS的组合的垃圾回收器,吞吐量最大,但是就是无法避免最大的STW的时间。
延时
JVM的GC持续时间也会影响到每次请求的响应时间。
可以通过堆中分代的大小,减少GC次数,减少GC带来的影响。
不过这个优先点应该是垃圾回收器的选择,选择低延迟的垃圾回收器。
JDK1.8首选G1,堆空间较小使用CMS。临界值一般是6~8G的堆空间。不过CMS本身有内存碎片和浮动垃圾的问题。推荐还是使用G1
1、新生代大小选择
2、老年代大小选择
调优是一个很大的概念,简单说就是把系统进行优化,但是站在一个系统的角度,能够干的事情太多了,我们一般把JVM调优分成以下三类:
♦ JVM预调优
♦ 优化JVM运行环境(慢、卡顿等)
♦ 解决JVM中的问题(OOM等)
调优中,现象最明显的是OOM,因为有异常抛出,当然它也只是作为调优的一部分。其次是慢和卡顿的问题。这些都在JVM三期中讲过。
最后才是GC调优,这个也就是今天讲课的内容,主要就是减少STW带来的影响,这些测试点和内容大小设置都需要根据不同的项目进行调整,所以这个是一个耐心活。
单击 “编辑” 按钮更改此文本。这是测试文本。