正常情况我们的jvm参数是如下设置:
‐Xms3072M ‐Xmx3072M ‐Xss1M ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐XX:SurvivorRatio=8
经过上面的分析 , 这样设置可能会由于动态对象年龄判断原则导致频繁full gc 。于是我们设置如下JVM参数 , 尽量避免触发full GC
‐Xms3072M ‐Xmx3072M ‐Xmn2048M ‐Xss1M ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐XX:SurvivorRatio=8
2. JVM优化这个原理在上面已经说过了 , 但是如果并发量从峰值400单/s , 一下冲到700~1000单/s 。这时候 , 很显然 , 又会触发Full GC了 , 因为内存对象从原来的80M,变成了160M甚至更多 , Survior区200M空间 , 他的一半小于160M, 所以会直接放入到老年代 。针对这个问题 , 我们来做参数优化 。
优化一:分代年龄从15变成5系统默认的分代年龄是15 , 也就是一个对象在Survivor两个区轮回15次才会进入到老年代 。15次大概是多长时间呢?我们来计算一下 , 按照参数来分析一下内存模型 , 如下图:
‐Xms3072M ‐Xmx3072M ‐Xmn2048M ‐Xss1M ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐XX:SurvivorRatio=8
文章插图
? 每秒钟产生80M垃圾 , 放入到Eden区 , Eden区一共1.6G , 预计20s放满 , 触发Minor GC, 然后大部分对象被回收 , 只有一小部分对象进入到Survivor区 。第二次回收的时候 , 上次进入Survivor区的大部分对象被垃圾回收 , 另一部分进入到另一个Survivor区 。这些进入到另一个Survivor的对象要经历15次Minor GC , 也就是年龄是15的时候 , 被转移到老年代 , 花费大约20s*15约5分钟的时间才能进入到老年代 。其实这些长期存活的对象都是JAVA运行或者spring运行是的一些java.lang.String, java.util.Math, 和一些bean对象 。既然这些对象本身是长期存活的 , 那么我们就没必要让他经历那么多代才进入到老年代 。
? 我们完全可以将默认的15岁改小一点 , 比如改为5 , 那么意味着对象要经过5次minor gc才会进入老年代 , 如果经历5次Minor GC还没有被回收 , 我们完全可以认为她就是要长期存活的对象了 , 将其移动到老年代 , 而不是继续一直占用survivor区空间 。整个过程时间不到两分钟 。
设置参数如下:
‐Xms3072M ‐Xmx3072M ‐Xmn2048M ‐Xss1M ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐XX:SurvivorRatio=8‐XX:MaxTenuringThreshold=5
优化二:大对象直接进入老年代对于多大的对象直接进入老年代合适呢?这个一般可以结合你自己系统看下有没有什么大对象生成 , 预估下大对象的大小 , 一般来说设置为1M就差不多了 , 很少有超过1M的大对象 , 这些对象一般就是你系统初始化分配的缓存对象 , 比如大的缓存List , Map之类的对象 。设置大对象直接进入老年代使用的参数:-XX:PretenureSizeThreshold参数设置如下:
‐Xms3072M ‐Xmx3072M ‐Xmn2048M ‐Xss1M ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐XX:SurvivorRatio=8‐XX:MaxTenuringThreshold=5 ‐XX:PretenureSizeThreshold=1M
优化三:替换垃圾收集器为ParNew + CMSJDK8默认使用的垃圾回收器是-XX:+UseParallelGC(年轻代)和-XX:+UseParallelOldGC(老年代) , 通常使用Parallel会有什么问题呢?经验告诉我们 , 当系统内存较大的时候(超过4G , 经验值) , 系统对停顿时间是比较敏感的 。通常大于4G内存 , 我们可以采用ParNew + CMS垃圾收集器 。可不可以使用G1收集器呢?G1收集器通常是内存大于8G时使用的 。内存小于8G时 , 在jdk8中G1收集器的算法耗费的内存要比CMS多 。所以这里我们替换垃圾收集器为ParNew + CMS 。设置使用ParNew + CMS的参数是:-XX:+UseParNewGC -XX:+UseConcMarkSweepGC经验: 很多使用jdk8的公司都是用时ParNew + CMS垃圾回收参数设置如下:
‐Xms3072M ‐Xmx3072M ‐Xmn2048M ‐Xss1M ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐XX:SurvivorRatio=8‐XX:MaxTenuringThreshold=5 ‐XX:PretenureSizeThreshold=1M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
替换成ParNew + CMS垃圾收集器能解决上面并发流量达到700~1000单/s的问题么?我们来分析一下:
推荐阅读
- 亚马逊跨境电商热销产品?亚马逊爆款打造思路
- 直电结合“3个1”,做好私域流量的关键在哪里?
- 关于流量的三大误区,还不懂,就别玩互联网了
- 推荐 7 个热门电商 GitHub 项目
- ntopng 的安装源码安装,一个非常棒的流量监控工具
- 掘金私域电商,关键点在哪?
- 百度用seo优化获取流量才是终网站优化的目的
- 《和平精英》一局经典模式耗多少流量?
- 百度联盟深挖流量价值
- 私域流量”是个大金矿,但不是每个人都能淘到金