亿级流量电商系统JVM模型参数二次优化( 二 )

  • 在Survivor区有一个对象动态年龄判断机制 。什么是对象动态年龄判断机制呢?
  • 当前放对象的Survivor区域里(其中一块区域 , 放对象的那块s区) , 一批对象的总大小大于这块Survivor区域内存大小的50%(-XX:TargetSurvivorRatio可以指定) , 那么此时大于等于这批对象年龄最大值的对象 , 就可以直接进入老年代了 , 
    例如:Survivor区域里现在有一批对象 , 年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50% , 此时就会把年龄n(含)以上的对象都放入老年代 。这个规则其实是希望那些可能是长期存活的对象 , 尽早进入老年代 。
    对象动态年龄判断机制一般是在minor gc之后触发的 。
    也就是说当在Survivor区经过几代的回收以后 , 如果对象总和大于Survivor区域的一半 , 则会直接放入到老年代 。Survivor是100M , 第10s的对象是80M , 大于100M , 会直接将这个对象放入到老年代 。
    亿级流量电商系统JVM模型参数二次优化

    文章插图
     
    1. 老年代一共有2G空间 , 2G空间执行多少次会满呢?2G/80M=25次 , 也就是发生25次(25秒)Minor GC就会触发一次Full GC 。这个频率就太高了 , 通常应该要很少触发Full GC , 起码也得1个小时触发一次 。而触发的原因是因为垃圾对象(这些对象1s后都变成垃圾了) , 这样肯定是不行的 。我们需要优化JVM参数 。
    3. JVM优化有问题有就解决问题 。问题的根本原因是老年代发生了Full GC , 为什么会发生Full GC呢?
    之所以80M对象会放到了老年代是因为每秒产生的数据 大于 Survivor区空间的一半 。所以 , 我们可以调整Survivor区大小 。通常我们不会修改默认的Eden:S1:S2的比例 , 所以 , 我们可以考虑从整体扩大新生代的内存空间 。假设我们扩大到2G , 让老年代是1G 。
    亿级流量电商系统JVM模型参数二次优化

    文章插图
     
    这时会怎么样呢?
    • Young区占2G , Eden区有1.6G ,  S1、S2各有200M 。
    这时在分析:
    亿级流量电商系统JVM模型参数二次优化

    文章插图
     
    • Eden区有1.6G , 每秒产生80M的对象放到Eden区 , 大约1.6G/80=20s放满 。
    • 放满以后触发Minor GC, 此时前19s的对象都已经成为垃圾被回收 , 第20s的对象被转移到S1区 。
    • 此时 , S1区有200M , 80<S1区空间的一半 , 所以不会转移到老年代 。这样第一次GC结束
    • 又过了20s , 进行第二次Minor GC , 这次Eden区又产生了1.52G的垃圾被回收 , 之前在S1区的80M对象也已经变成垃圾被回收 。新的80M对象被放入到S2区 。没有进入到老年代 。
    • 以此类推 , 第三次 , 第四次 , 垃圾对象不会再进入老年代 , 因此也不会在发生Full GC.
    由此分析 , 大大降低了Full GC发生的频率 。
    最终参数设置:
    -Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M为了更清晰的看到效果 , 可以打印GC详细日志-XX:+PrintGCDetails4. 总结通过上面的数据分析 , 我们要养成一个习惯 , 做任何事情都是要有理有据 , 不能是拍脑袋就说出来的 。一定要能够经得起验证的 。
    二、亿级流量jvm参数优化--使用parNew和CMS垃圾收集器1. 需求分析上面的参数设置 , 帮我们解决了多次触发Full GC的问题 , 通过调整参数以后 , 我们看出在预期正常情况下 , 基本不会触发Full GC 。但如果有意外情况呢?比如 , 我们的一台服务器能够承受的最大并发量是400/s , 但如果在秒杀的时候 , 并发量超过了这种情况是在不发生意外的情况下 。假如并发流量达到1000 , 内存模型是怎么样的呢?
    亿级流量电商系统JVM模型参数二次优化

    文章插图
     
    根据这个估算模型 , 正常情况下订单系统可以承接的订单并发量是400单/s , 但遇到某一个大促活动 , 很可能并发量冲到700单/s, 1000单/s , 这是一秒产生的垃圾就不是60M了 , 可能是120M , 甚至更多 。根据之前的分析 , 这时又会频繁的触发Full GC了 。当然了 , 我们有很多办法来控制并发量 , 比如限流、扩容 。但这里我们从JVM的角度来分析 , 如何处理这个问题 。


    推荐阅读