高并发场景下JVM调优实践之路

一、背景

2021年2月,收到反馈,视频APP某核心接口高峰期响应慢,影响用户体验。

通过监控发现,接口响应慢主要是P99耗时高引起的,怀疑与该服务的GC有关,该服务典型的一个实例GC表现如下图:

可以看出,在观察周期里:

  • 平均每10分钟Young GC次数66次,峰值为470次;

  • 平均每10分钟Full GC次数0.25次,峰值5次;

可见Full GC非常频繁,Young GC在特定的时段也比较频繁,存在较大的优化空间。由于对GC停顿的优化是降低接口的P99时延一个有效的手段,所以决定对该核心服务进行JVM调优。

二、优化目标

  • 接口P99时延降低30%

  • 减少Young GC和Full GC次数、停顿时长、单次停顿时长

由于GC的行为与并发有关,例如当并发比较高时,不管如何调优,Young GC总会很频繁,总会有不该晋升的对象晋升触发Full GC,因此优化的目标根据负载分别制定:

目标1:高负载(单机1000 QPS以上)

  • Young GC次数减少20%-30% ,Young GC累积耗时不恶化;

  • Full GC次数减少50%以上,单次、累积Full GC耗时减少50%以上,服务发布不触发Full GC。

目标2:中负载(单机500-600)

  • Young GC次数减少20%-30% ,Young GC累积耗时减少20%;

  • Full GC次数不高于4次/天,服务发布不触发Full GC。

目标3:低负载(单机200 QPS以下)

  • Young GC次数减少20%-30% ,Young GC累积耗时减少20%;

  • Full GC次数不高于1次/天,服务发布不触发Full GC。

三、当前存在的问题

当前服务的JVM配置参数如下:

-Xms4096M -Xmx4096M -Xmn1024M
-XX:PermSize=512M
-XX:MaxPermSize=512M
复制代码

单纯从参数上分析,存在以下问题:

**未显示指定收集器 **

JDK 8默认搜集器为ParrallelGC,即Young区采用Parallel Scavenge,老年代采用Parallel Old进行收集,这套配置的特点是吞吐量优先,一般适用于后台任务型服务器。

比如批量订单处理、科学计算等对吞吐量敏感,对时延不敏感的场景,当前服务是视频与用户交互的门户,对时延非常敏感,因此不适合使用默认收集器ParrallelGC,应选择更合适的收集器。

Young区配比不合理

当前服务主要提供API,这类服务的特点是常驻对象会比较少,绝大多数对象的生命周期都比较短,经过一次或两次Young GC就会消亡。

再看下当前JVM配置

整个堆为4G,Young区总共1G,默认-XX:SurvivorRatio=8,即有效大小为0.9G,老年代常驻对象大小约400M。

这就意味着,当服务负载较高,请求并发较大时,Young区中Eden + S0区域会迅速填满,进而Young GC会比较频繁。

另外会引起本应被Young GC回收的对象过早晋升,增加Full GC的频率,同时单次收集的区域也会增大,由于Old区使用的是ParralellOld,无法与用户线程并发执行,导致服务长时间停顿,可用性下降, P99响应时间上升。

未设置

-XX:MetaspaceSize和-XX:MaxMetaspaceSize

Perm区在jdk 1.8已经过时,被Meta区取代,
因此-XX:PermSize=512M -XX:MaxPermSize=512M配置会被忽略,
真正控制Meta区GC的参数为
-XX:MetaspaceSize:
Metaspace初始大小,64位机器默认为21M左右
 
-XX:MaxMetaspaceSize:
Metaspace的最大值,64位机器默认为18446744073709551615Byte,
可以理解为无上限
 
-XX:MaxMetaspaceExpansion:
增大触发metaspace GC阈值的最大要求
 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值