JVM从入门到精通(七):GC常用参数,Method Area,JVM调优案例分析

GC常用参数

  • -Xmn -Xms -Xmx -Xss
    年轻代 最小堆 最大堆 栈空间
  • -XX:+UseTLAB
    使用TLAB,默认打开
  • -XX:+PrintTLAB
    打印TLAB的使用情况
  • -XX:TLABSize
    设置TLAB大小
  • -XX:+DisableExplictGC
    System.gc()不管用 ,FGC
  • -XX:+PrintGC
  • -XX:+PrintGCDetails
  • -XX:+PrintHeapAtGC
  • -XX:+PrintGCTimeStamps
  • -XX:+PrintGCApplicationConcurrentTime (低)
    打印应用程序时间
  • -XX:+PrintGCApplicationStoppedTime (低)
    打印暂停时长
  • -XX:+PrintReferenceGC (重要性低)
    记录回收了多少种不同引用类型的引用
  • -verbose:class
    类加载详细过程
  • -XX:+PrintVMOptions
  • -XX:+PrintFlagsFinal -XX:+PrintFlagsInitial
    必须会用
  • -Xloggc:opt/log/gc.log
  • -XX:MaxTenuringThreshold
    升代年龄,最大值15
  • 锁自旋次数 -XX:PreBlockSpin 热点代码检测参数-XX:CompileThreshold 逃逸分析 标量替换 …
    这些不建议设置

JVM调优第一步,了解JVM常用命令行参数

  • JVM的命令行参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

  • HotSpot参数分类

    标准: - 开头,所有的HotSpot都支持

    非标准:-X 开头,特定版本HotSpot支持特定命令

    不稳定:-XX 开头,下个版本可能取消

    java -version

    java -X

试验用程序:

import java.util.List;
import java.util.LinkedList;

public class HelloGC {
  public static void main(String[] args) {
    System.out.println("HelloGC!");
    List list = new LinkedList();
    for(;;) {
      byte[] b = new byte[1024*1024];
      list.add(b);
    }
  }
}

查看默认参数
默认参数查看GC详细信息
在这里插入图片描述

一条GC信息的详细信息如下:
在这里插入图片描述

关于上图中的Times含义:在linux中的times代表:

在这里插入图片描述

Heap Dump的含义

eden space 5632K, 94% used [0x00000000ff980000,0x00000000ffeb3e28,0x00000000fff00000)
                            后面的内存地址指的是,起始地址,使用空间结束地址,整体空间结束地址

在这里插入图片描述

调优实战

在这里插入图片描述

调优前的基础概念:
  1. 吞吐量:用户代码时间 /(用户代码执行时间 + 垃圾回收时间)
  2. 响应时间:STW越短,响应时间越好

所谓调优,首先确定,追求啥?吞吐量优先,还是响应时间优先?还是在满足一定的响应时间的情况下,要求达到多大的吞吐量…

问题:

科学计算,吞吐量。数据挖掘,thrput。吞吐量优先的一般:(PS + PO)
响应时间:网站 GUI API (1.8 G1)

什么是调优?

  1. 根据需求进行JVM规划和预调优
  2. 优化运行JVM运行环境(慢,卡顿)
  3. 解决JVM运行过程中出现的各种问题(不完全等同于解决OOM的问题,因为前面两项也很重要)

并发:

  • QPS
  • TPS
    淘宝双11并发历年最高54万,据说12306并发比淘宝更高,号称上百万

调优,从规划开始

  • 调优,从业务场景开始,没有业务场景的调优都是耍流氓

  • 无监控(压力测试,能看到结果),不调优(可以调整业务逻辑)

  • 步骤:

    1. 熟悉业务场景(没有最好的垃圾回收器,只有最合适的垃圾回收器)
      1. 响应时间、停顿时间 [CMS G1 ZGC] (需要给用户作响应)
      2. 吞吐量 = 用户时间 /( 用户时间 + GC时间) [PS]
    2. 选择回收器组合
    3. 计算内存需求(没有一定之规,是经验值。 1.5G -> 16G,突然卡顿了,为啥?)
    4. 选定CPU(预算能买到的,当然是越高越好,CPU多核,可以多线程运行呀)
    5. 设定年代大小、升级年龄
    6. 设定日志参数,这是Java虚拟机的参数,也可以在Tomcat里面配置,貌似是在叫catalinaoptions里面指定java日志的参数。
      1. -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
        5个日志文件,循环产生。生产环境中的日志参数一般这么设置。
        %t是生成时间的意思。
        在这里插入图片描述
      2. 或者每天产生一个日志文件
    7. 观察日志情况

如何根据需求进行JVM规划和预调优?

有人要问你,你应该选用多大的内存?什么样的垃圾回收器组合?你怎么回答?

  • 案例1:垂直电商,最高每日百万订单,处理订单系统需要什么样的服务器配置?

    这个问题比较业余,因为很多不同的服务器配置都能支撑(1.5G 16G 都有可能啊)

    我们做一个假设吧,1小时360000个订单。集中时间段, 100个订单/秒,(找一小时内的高峰期,可能是1000订单/秒)。我们就要找到这个最高峰的时间,保证你的架构能够承接的住

    大多数情况下,是靠经验值,然后做压测。

    如果非要计算的话,你预估一下,一个订单对象产生需要多少内存?512K * 1000 = 500M内

    专业一点的问法:要求响应时间在多少时间的情况下,比如100ms,我们去挑一个市面上性价比比较高的服务器,做压测去测试,再不行加内存,再不行,就上云服务器…
    这样说就OK了

  • 案例2:12306遭遇春节大规模抢票应该如何支撑?(这个是架构上的一个设计,和调优关系不大)

    12306应该是中国并发量最大的秒杀网站:号称并发量最高100W

    架构模型:CDN -> LVS -> NGINX -> 业务系统 -> 100台机器,每台机器1W并发(单机10K问题),目前这个问题已解决,主要是用redis
    .

    业务流程:普通电商订单 -> 下单 ->订单系统(IO)减库存 ->生成订单,等待用户付款

    12306的一种可能的模型,是异步来进行的: 下单 -> 减库存 和 订单(redis kafka) 同时异步进行 ->等付款,付完款,持久化到Hbase, MySQL等等
    .
    减库存最后还会把压力压到一台服务器,怎么办?

    可以做分布式本地库存 + 单独服务器做库存均衡

    大流量的处理方法:分而治之,每台机器只减自己机器上有的库存
    流量倾斜的问题怎么解决?比如有的机器上已经没库存了,有的机器上还剩很多?
    这时候你还需要一台单独的服务器,去做所有服务器的平衡,如果某台服务器没库存了,从别的机器上挪一些过去。

  • 怎么得到一个事务会消耗多少内存?
    1、弄台机器,看能承受多少TPS?是不是达到目标?扩容或调优,让它达到
    2、用压测来确定

优化环境

  1. 这个可以稍微改一下写进简历中
    有一个50万PV的文档资料类网站(从磁盘提取文档到内存)原服务器32位,1.5G
    的堆,用户反馈网站比较缓慢。因此公司决定升级,新的服务器为64位,16G的堆内存,结果用户反馈卡顿十分严重,反而比以前效率更低了!
    1. 为什么原网站慢?
      因为很多用户浏览数据,很多用户浏览导致很多数据Load到内存,产生了很多文档对应的Java包装对象(而不是文档对象,文档本身可以走Nginx)。内存不足,频繁GC,STW长,响应时间变慢
    2. 为什么会更卡顿
      内存越大,FGC时间越长
    3. 咋办
      PS 换成 PN + CMS,或者 G1
      或者业务上的调整,文档不走JVM
  2. 系统CPU经常100%,如何调优?(面试高频)
    这样回答:推理过程是:CPU100%,那么一定有线程在占用系统资源,所以
    1. 找出哪个进程cpu高(top命令)
    2. 该进程中的哪个线程cpu高(top -Hp)
    3. 如果是java程序,导出该线程的堆栈 (jstack)
    4. 查找哪个方法(栈帧)消耗时间,哪个方法调用的哪个方法 (jstack),然后去看这个方法的代码
    5. 工作线程占比高 | 垃圾回收线程占比高
  3. 系统内存飙高,如何查找问题?(面试高频)
    1. 导出堆内存 (jmap)
    2. 分析 (jhat jvisualvm mat jprofiler … )
  4. 如何监控JVM
    1. jstat jvisualvm jprofiler arthas top…
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章