java中双12压测引出的线上Full GC怎么排查

发布时间:2021-12-08 09:20:18 作者:iii
来源:亿速云 阅读:192
# Java中双12压测引出的线上Full GC怎么排查

## 前言

在电商大促(如双12)期间,系统往往会面临比日常高出数倍的流量冲击。为了确保系统稳定性,压测成为必不可少的环节。然而,压测过程中暴露的Full GC问题却可能成为系统性能的"隐形杀手"。本文将从一个真实的双12压测案例出发,深入剖析Full GC问题的排查思路、工具使用和解决方案。

---

## 一、问题现象:压测期间的Full GC告警

### 1.1 压测场景描述
- **系统架构**:分布式Java服务(Spring Boot + Dubbo),JDK1.8
- **压测指标**:QPS目标5万,响应时间<200ms
- **JVM参数**:
  ```java
  -Xms4g -Xmx4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200

1.2 异常表现


二、初步排查:基础数据收集

2.1 获取GC日志

通过JVM参数开启详细GC日志:

-XX:+PrintGCDetails -XX:+PrintGCDateStamps 
-Xloggc:/path/to/gc.log

示例日志片段:

2023-12-12T14:25:03.123+0800: [Full GC (Allocation Failure) 
  4095M->3892M(4096M), 1.234 secs]

2.2 关键指标分析

指标 正常值 压测期间值
Young GC频率 10次/分钟 50次/分钟
Full GC频率 0次/小时 15次/分钟
堆内存使用率 60%~70% 98%~100%
Old区增长速率 10MB/分钟 500MB/分钟

三、深度诊断:工具链使用

3.1 jstat实时监控

jstat -gcutil <pid> 1000 10

输出示例:

  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00  96.88  45.12  98.67  95.11  92.45   312    45.123   15    12.456   57.579

3.2 堆内存Dump分析

jmap -dump:live,format=b,file=heap.hprof <pid>

使用MAT工具分析后发现: - 内存泄漏点:一个静态HashMap占用了1.2GB内存 - 对象类型:缓存了未过期的商品详情DTO

3.3 线程堆栈分析

jstack -l <pid> > thread.txt

发现大量线程阻塞在:

"DubboServerHandler-192.168.1.1:20880-thread-32" #32 daemon prio=5 os_prio=0 tid=0x00007f48740e4800 nid=0x1e3 waiting on condition [0x00007f486b7e7000]
   java.lang.Thread.State: WTING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000006c0008e98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)

四、根因定位:问题层层剖析

4.1 直接原因

4.2 深层原因

  1. 代码缺陷

    public class ProductCache {
       // 错误的静态缓存声明
       private static Map<Long, ProductDTO> cache = new HashMap<>(); 
    }
    
  2. 压测场景特殊性

    • 压测工具构造的商品ID范围远超生产环境
    • 缓存失效时间设置为24小时(实际业务需求仅需5分钟)
  3. JVM参数缺陷

    // 缺少关键参数
    -XX:InitiatingHeapOccupancyPercent=45  // 默认值过高(45)
    

五、解决方案与优化措施

5.1 紧急恢复方案

  1. 动态扩容
    
    java -Xms8g -Xmx8g ...  # 临时扩大堆内存
    
  2. 缓存清理
    
    // 通过Arthas热修复
    ognl '@com.example.ProductCache@cache.clear()'
    

5.2 长期优化方案

代码层面

// 使用Guava Cache替代原生Map
LoadingCache<Long, ProductDTO> cache = CacheBuilder.newBuilder()
    .maximumSize(10000)
    .expireAfterWrite(5, TimeUnit.MINUTES)
    .build(...);

JVM参数优化

-XX:+UseG1GC 
-XX:InitiatingHeapOccupancyPercent=35  # 降低IHOP阈值
-XX:ConcGCThreads=4                   # 增加并发GC线程
-XX:G1HeapRegionSize=4m               # 调整Region大小

架构改进


六、验证与效果

6.1 二次压测结果

指标 优化前 优化后
Full GC次数 15次/分钟 0次/小时
P99响应时间 650ms 120ms
系统吞吐量 3万QPS 5.8万QPS

6.2 监控曲线对比

java中双12压测引出的线上Full GC怎么排查


七、经验总结与最佳实践

  1. 压测环境配置原则

    • 必须与生产环境保持1:1的JVM参数
    • 压测数据应当模拟真实业务分布
  2. 缓存使用黄金法则

    • 避免使用静态集合作为缓存
    • 必须设置合理的上限和过期时间
  3. G1GC调优要点

    // 关键参数组合
    -XX:G1NewSizePercent=30 
    -XX:G1MaxNewSizePercent=60
    -XX:G1HeapWastePercent=5
    
  4. 建立常态化检查机制

    • 每周GC日志分析
    • 内存泄漏检测纳入CI流程

附录:常用排查命令速查表

场景 命令/工具 关键参数
实时GC监控 jstat -gcutil 间隔时间(ms)
堆内存分析 jmap -dump + MAT format=b,file=
线程分析 jstack + TDA -l 显示锁信息
动态诊断 Arthas trace/watch/ognl
网络连接分析 netstat -antp -n 禁用域名解析

”`

(注:实际文章应包含更多具体日志示例、代码片段和图表说明,此处为保持简洁做了适当精简)

推荐阅读:
  1. 一次tomcat压测调优记录
  2. 线上FullGC频繁的排查

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:cinder如何配置多ceph储存池

下一篇:HP EVA4400/6400/8400/P6000数据恢复的解决方案是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》