zoukankan      html  css  js  c++  java
  • 服务端调优与JVM调优

    一、安装Jmeter

      下载地址:http://jmeter.apache.org/download_jmeter.cgi

      下载后直接进入bin目录,直接运行jmeter即可,我这里用得是mac,直接sh jmeter

      1、调整语言

        Options--Choose Languages--Chinese(Simple lified)

      2、添加jmeter-plugin插件

        下载地址:链接: https://pan.baidu.com/s/1RXD6JnT5LJx5mBvxmUf7JQ 提取码: 90ni

        下载后文件为plugins-manager.jar格式,将其放入jmeter安装目录下的lib/ext目录,然后重启jmeter,即可。

      3、添加jpgc插件

        这个插件可以监测TPS,RT等重要指标。

        选项-plugin Manager --jpgc - Standard Set,安装后重启。

    二、压测

      写一个简单的demo

        @RequestMapping(value = "/goods/detail/nocache/{seckillId}",method = RequestMethod.GET)
        public TbSeckillGoods findOneNoCache(@PathVariable Integer seckillId){
            TbSeckillGoods  seckillGoods = seckillGoodsMapper.selectByPrimaryKey(id);
        }

      运行:

    nohup java -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

      这就是一个最简单的使用主键查询。

       1、添加测试项(01-秒杀系统测试方案)

        测试方案--添加--线程(用户)--线程组,设置测试接口名称(01-商品详情测试方案)。

        测试接口--添加--取样器--HTTP请求(01-商品详情HTTP请求)

        测试接口--添加--监听器--聚合报告(02-商品详情聚合报告)

        测试接口--添加--监听器--查看结果树(03-商品详情结果树)

        测试接口--添加--监听器--jp@gc - Transactions per Second (04-商品详情接口TPS)

        测试接口--添加--监听器--jp@gc - Response Times Over Time(05-商品详情响应时间)

          

      2、验证

        点击开始,然后查看结果树中的响应数据,可以看到正常返回,验证无误。

          

       3、正式压测

        修改测试方案中的线程数和循环次数,这里模拟20W个样本,线程数为4000,启动时间为5秒,循环次数为50次,这几个参数的意思是:在5秒内顺序启动4000个线程,这个操作循环50次。这50次循环是并行执行的。

        (1)TPS

          

         如果服务的TPS存在明显的抖动,说明要么服务有问题,要么网络有问题。TPS性能曲线不能出现明显抖动(当前条件当测试演变比较稳定),查看服务问题。

         这里再说明一下TPS和QPS,TPS ,QPS,吞吐量:大多数情况下,单独一个接口: TPS = QPS = 吞吐量(每秒请求数)

          

        (2)RT

          

         (3)聚合报告

          

           # 样本: 测试的样本数 20w

          # 平均值: 所有的请求从发送请求到请求结束所消耗的平均时间

          # 中位数:50%的请求在713ms之内响应结束

          # 90%百分位:90%的请求在782ms之内响应结束

          最小值: 请求消耗的最小时间

        (4)测试参数

          

    三、服务端调优

      1、分析与调优

      查看线程数:pstree -p 进程号 | wc -l

    pstree -p 3769 | wc -l

      如果没有命令,需要安装pstree:

    yum -y install psmisc 

          

      经过测试,发现服务器只产生了 200 个线程来处理业务请求,增加线程数,可以提升吞吐能力;考虑 cpu 处理能力的问题,cpu 上下文切换耗时,抢占 cpu 等待问题;考虑 cpu 性能损耗问题,使用 top 查看即可;

      Springboot内置的Tomcat配置信息在:spring-boot-autoconfigure-2.2.5.RELEASE.jar中的spring-configuration-metadata.json中

          

      

      其中比较重要的三个配置项:最大连接数、服务队列、最大线程数,三者的关系如下图所示:

        首先使用等待队列接收请求,然后创建连接,然后执行业务,如果当最大连接数,等待队列都已经满了,tomcat 服务就会拒绝连接。

          

       (1)最大连接数:

          

       (2)服务队列

          

       (3)最大线程数

          

       由于部署应用的服务器是4C8G,单个线程默认为200个线程,这里4个CPU,将线程数调整为800。

    server:
      port: 9000
      tomcat:
        # 编码格式
        uri-encoding: utf-8
        # 服务队列
        accept-count: 1000
        # 最大连接数
        max-connections: 20000
        # 最大线程数
        max-threads: 800
        # 初始化线程,应对突发流量
        min-spare-threads: 10

      2、验证压测

          

       经过 20w 个样本的测试,发现 TPS 没有发生任何的变化,TPS = 2700

          

       可以发现在服务器最大线程数增加了 4 倍,理论上来说,TPS 一定会增加 4 倍,但是根据实际测试结果,发现 TPS 没有任何的变化,这是因为没有执行任何业务,不是一个耗时的操作,主键查询:0-10ms 结束,无需要对一个不耗时操作进行调优。

      结论:调优应该是对于耗时操作进行调优。

      3、模拟耗时操作调优

      模拟一个耗时操作

          public TbSeckillGoods findOne(Integer id){
                //直接从数据库查询
                //主键查询 : cpu不耗时操作
                TbSeckillGoods  seckillGoods = seckillGoodsMapper.selectByPrimaryKey(id);
                //计算对象大小
                //模拟程序耗时操作,如果方法是一个笔记耗时的操作,性能优化非常有必要的!!
                  try {
                      Thread.sleep(1000);
                      LOGGER.info("模拟耗时操作,睡眠1s时间!");
                      LOGGER.info("对象占用jvm堆内存大小: {}", RamUsageEstimator.humanSizeOf(seckillGoods));
                } catch (InterruptedException e) {
                      e.printStackTrace();
                }
                //返回结果
                return seckillGoods;
          }

       在未调优的情况下进行压测:没有优化之前,对于一个耗时操作来说,TPS = 200

          

      调优后压测:调优之后的 TPS 情况(线程数增加:800) -- 理论上: cpu 没有任何压力,TPS 应该会获得倍数的提升,提升 4 倍

          

       经过测试:发现 TPS 有了 4 倍的提升,tps = 800

      4、Keepalive

      客户端和服务端连接的时候,为了防止频繁建立连接,释放连接,浪费资源,这样就好损耗的性能,造成性能严重下降;

           

       可以发现: jmeter connection : keep -alive 长连接

          

         查看连接数:

    netstat -anp | grep ESTABLISHED | wc -l

      

       但是keepalive 长连接本身也会消耗大量资源,如果这些长连接不能及时释放,长连接将会占用大量资源,系统 TPS 就会上不去;因此对 keepalive 设置一个比较合理的连接数;另外: 长连接也必须及时释放,没有请求使用这个链接,这个链接一段时间必须释放;

      可以在代码中定制tomcat服务器的长链接设置。

    @Component
    public class WebServerConfig implements WebServerFactoryCustomizer<ConfigurableWebServerFactory>{
        // 定制tomcat服务器
        @Override
        public void customize(ConfigurableWebServerFactory configurableWebServerFactory) {
            ((TomcatServletWebServerFactory)configurableWebServerFactory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
                // 获取tomcat连接器
                @Override
                public void customize(Connector connector) {
                    // 获取protocol
                    Http11NioProtocol protocolHandler = (Http11NioProtocol) connector.getProtocolHandler();
                    // 如果keepalive连接30s,还没有人使用,释放此链接
                    protocolHandler.setKeepAliveTimeout(30000);
                    // 允许开启最大长连接数量,4cpu,8gb
                    protocolHandler.setMaxKeepAliveRequests(10000);
                }
            });
        }
    }

     四、线上问题分析

    (一)问题分类

      发现问题,解决问题 (测试时候发现一些问题,修复,调试,调优 , 更多的时候: 上线以后发现一些问题,解决问题)系统出现问题分类:

      1、系统异常

        CPU 占用率过高,磁盘满了,磁盘 IO 阻塞,网络流量异常等等问题

        排查指令:TOP,free,dstat , pstack , vmstat , strace 获取异常信息,排查系统异常

      2、业务异常

        流量太大系统扛不住,耗时长,线程死锁,并发问题,频繁 full gc ,oom 等等

        排查: top, jstack ,pstack , strack 日志

    (二)问题排查

      1、TOP命令

        Top 指令监控 cpu 使用情况,根据 cpu 使用分析系统整体运行情况

          

         关注性能指标: load average : 1 分钟之内 cpu 平均使用率,5 分钟之内 cpu 平均使用率,15分钟之内 cpu 平均使用率;如果1分钟之内cpu使用率较高,但是5分钟或15分钟内较低,有可能是短暂的流量激增导致,可以暂时不用关心。

        单核心 cpu:

          1)load average < 1 , 表示 cpu 毫无压力,比较空闲,运行流畅

          2)load average = 1 , 表示 cpu 刚刚被占满,没有可供提供的 cpu 资源

          3)load average > 1 , 表示 cpu 已经满负荷运作,线程处于阻塞等待状态,等待 cpu资源

          4)load average > 5 , 表示 cpu 已经处于超负荷运作,线程已经大面积阻塞,必须进行优化处理;

        4 核心 cpu:

          1)load average < 4 , 表示 cpu 毫无压力,比较空闲,运行流畅

          2)load average = 4 , 表示 cpu 刚刚被占满,没有可供提供的 cpu 资源

          3)load average > 4 , 表示 cpu 已经满负荷运作,线程处于阻塞等待状态,等待 cpu资源

          4)load average > 10 , 表示 cpu 已经处于超负荷运作,线程已经大面积阻塞,必须进行优化处理;

      2、Free命令

        Free 排查线程问题:内存问题很多时候引起 cpu 较高的原因。

          

      3、磁盘

        Df 指令查看磁盘问题,查看磁盘使用情况,有时候服务出现问题,其实就是磁盘出现问题。

          

      4、网络

        Dstat 命令: 集成 vmstat , iostat , netstat ,工具完成任务,-c 查看 cpu 使用情况, -d 查看磁盘读写,-n 网络状态 -l 显示系统负载

        详细的参数展示可以参考下这篇文章:http://www.yishimei.cn/network/850.html

          

     五、JVM调优概述

    (一)为什么调优

      1、调优的目的

        调优的目的就是为了提升项目性能,避免项目出现一些不可预知的 bug(频繁 fullgc,oom);

        (1)jvm 堆内存空间对象太多(Java 线程,垃圾对象),导致内存空间被占满,程序跑不动 –性能严重下降,通过调优:及时释放内存空间

        (2)垃圾回收线程太多(频繁的垃圾回收,垃圾回收线程也会占用 CPU,内存资源),必然导致程序性能下降,通过调优:防止频繁的 gc

        (3)垃圾回收导致 STW (stop the world : 停止整个世界 --- 整个业务执行全部暂停),通过调优:尽可能减少 gc 次数

          

      2、JVM 调优的本质

        jvm 调优本质就是(对内存空间的调优)及时是否垃圾对象占用的内存空间,让程序性能得以提升,让其他业务线程可以使用内存空间;

      3、如果把 jvm 堆内存设置的足够大(无限大),是不是不需要垃圾回收?

        理论上确实可以考虑内存空间垂直扩容,解决 JVM 内存问题,但是同样存在问题:

          (1)成本问题 --- 高性能服务器

          (2)一旦触发垃圾回收 --- gc 时间比较长

          (3)微服务架构场景下(每一个服务都是一个微小,独立的服务) --- 水平扩展

          (4)寻址能力的问题(JVM 默认内存调优分配空间: 32GB,超过32G就不会进行调优):

              32 位操作系统: 2~32 = 4GB 内存空间 --- Java 对象 8 字节 指针压缩 : 4GB *8 = 32GB

              64 位操作系统 2~64 = 16384PB

        小结: JVM 内存空间设置,必须设置一个大小合适的内存空间,不能太大,也不能设置太小;

          (1)成本问题 --- 高性能服务器

          (2)一旦触发垃圾回收 --- gc 时间比较长

          (3)微服务架构场景下(每一个服务都是一个微小,独立的服务) --- 水平扩展

    (二)JVM 调优原则

      1、gc 时间足够小(堆内存设置足够小)

        此原则就是让我们在设置堆内存空间时候,不要把内存空间设置的太多,防止 gc 消耗太多的时间;

      2、gc 的次数足够少(堆内存空间设置的足够大)

        GC 触发条件: 内存空间被占满,立即触发垃圾回收(ps,po),也就是说内存空间被占满一次,就发生一次 gc,占满多次就发生多次 gc;

      3、发生 fullgc 周期足够长(最好不要发生 fullgc)

        (1)metaspace 元数据空间大小设置合适 ,metaspace 一旦发生扩容,fullgc 就会发生

        (2)老年代空间设置一个合理的大小,防止 fullgc

        (3)尽量让垃圾对象在年轻代回收(90%)

        (4)尽量防止大对象的产生,一旦大对象多了以后,就可能发生 fullgc , 甚至 OOM

    (三)JVM 调优原理

      1、JVM 调优本质:

         回收垃圾,及时释放内存空间。在 Java 堆内存中,那些没有被引用的对象就是垃圾(高并发模式下,大量的请求在内存空间中创建了大量的对象,这些对象不会主动消失,必须进行垃圾回收,当然 Java 语言自己提供了垃圾回收器,帮助我们回收垃圾,JVM 垃圾是自动进回收的)

        JVM 提供 2 种方法寻找垃圾:引用计数法和根可达算法

      2、垃圾清理算法:

        mark-sweep 标记清除算法、copying 拷贝算法、mark-compact 标记压缩算法。

        标记清除算法:

          过程:(1)使用根可达算法找到垃圾对象,对垃圾对象进行标记(仅仅是做一个标记);(2)对标记的对象做清除。

          优点: 简单,高效;

          缺点: 产生很多的内存碎片

        copying 算法 – 一开始把内存空间一分为二,分为 2 份大小相同的内存空间,一般内存空间作为备份使用。

          过程:(1)选择(寻址)存活对象;(2)把存活对象拷贝另一半空闲空间中,且是连续的空间;(3)把存活对象拷贝结束后,另一半空间中就是垃圾对象(全是垃圾对象),直接清除即可;

          优点:简单,内存空间是连续的,不会存在内存碎片

          缺点:内存空间的浪费

        mark-compact 标记压缩算法:

          过程:(1)标记垃圾(只标记,不清除);(2)再次扫描内存空间(未被标记的对象就是存活对象),找到存活对象,且把存活对象向一端移动(一端内存空间是连续的)--压缩,整理;(3)当存活对象全部被移动到一端后,另一端就是垃圾对象,直接清除即可

      3、垃圾回收器

        Java 语言提供了 10 种垃圾回收器:

          

       特点:

        (1)Serial(年轻代) Serial Old(老年代) , parNew(年轻代) CMS(老年代) , Parallel Scavenge(年轻代) Parallel Old(老年代) 都属于物理分代模型中垃圾回收器,年轻代,老年代模型,分别都使用不同的垃圾回收器;

        (2)G1 在逻辑上分代模型,使用非常方便;关于年轻代,老年代只需要使用 g1 一个垃圾回收器即可;

        (3)zgc zgc 是 jdk11 新加入的垃圾回收器,在试验阶段;

        (4)shenandoah openJDK 的垃圾回收器

        (5)epsilon 是 debug 使用的,在调试环境下,验证 jvm 内存参数设置的可行性;

        (6)Serial 和 Serial Old 串行化的垃圾回收器

        (7)parNew和CMS : 响应时间优先垃圾回收器组合 (fullgc 比较多,无法避免 --- cms)

        (8)parallel scavenge 和 parallel old : 吞吐量优先的垃圾回收器组合

      常用垃圾回收器组合:

        (1)Serail + Serial Old : 串行化的垃圾回收器,适合单核心的 cpu 服务器

        (2)parNew + CMS : 响应时间有些的垃圾回收器,并行,并发垃圾

        (3)Parallel Scavenge+Parallel Old : 并行垃圾回收器

        (4)g1 逻辑上分代垃圾回收器

      4、垃圾回收器原理

      (1)Serial+Serial Old

        Serial : 年轻代垃圾回收器,单线程垃圾回收器; Serial Old : 老年代的垃圾回收器,也是一个单线程的垃圾回收器,适合单核心 cpu 情况。

          

         注意:1、stw : 任何垃圾回收器都无法避免 stw(stop the world : 当进行 gc 的时候,整个业务线程必须暂停),如果 stw 时间过长,或者 stw 发生次数过多,都会影响程序的性能;2、垃圾回收线程: 多线程,单线程,并发,并行

      (2)Parallel Scavenge + Parallel Old

        Parallel Scavenge+Parallel Old : 并行垃圾回收器,吞吐量优先的垃圾回收器组合,是 JDK8 默认垃圾回收器组合;(并行: 同一个时候,同时执行,并行;并发: 在一段时间内,多个线程抢占式交叉执行,叫做并发模式;)

        PS + PO : 垃圾回收器进行垃圾回收器的时候,采用多线程模式回收垃圾

          

       (3)parNew+CMS

        parNew : 年轻代垃圾回收器,并行的垃圾回收器;

          

         CMS : 并发垃圾回收器,响应时间优先垃圾回收器

          

             初始化标记:(寻址垃圾比较耗时)只标记跟根对象相关联的对象,因此耗时比较少,且采用单线程模式标记

            并发标记: (寻址垃圾比较耗时)为了防止 gc 时候 stw, 因此使用并发模式标记垃圾,也就是说让业务线程和 gc 标记线程交叉执行;

            重新标记: 重新标记漏标的对象,此时漏标对象比较少,因此耗时比较少

            并发清理:(清理垃圾比较耗时) 采用并发模式清理垃圾,业务线程和清理垃圾线程交叉执行,以此减少业务线程停顿的时间;

      (4)G1

        G1 jdk11 成为了默认的垃圾回收器;采用了分区的思想;对内存进行逻辑上分代;采用RememberSet 集合记录每一个 region 区域

      5、内存分代模型

          

      通过内存分代模型: 大多数对象都会在年轻代被回收(90%+),超过 15 次没有被回收的对象就进入 old 区域。垃圾回收器触发时机:

        (1)ps + po : 当内存空间(eden,old)被占满后,触发垃圾回收器

        (2)cms 垃圾回收器

            jdk1.5 : 68% ,当 eden 区域被装载到 68%的时候,触发垃圾回收器

            jdk1.6+ : 92% 触发垃圾回收器

    六、JVM调优实战

    (一)调优实战

      JVM 调优的本质就是 GC(垃圾回收,及时释放掉内存,提供给其他的线程使用—并发模式),每次 GC 的时候,导致业务线程 STW, 因此必须进行综合的考量:频繁的 gc 也会导致性能下降

      JVM 调优其实就是选择一个合适的垃圾回收器(在不同的场景下),设置一些合理垃圾回收参数(参考 JVM 内存模型),分配合理的内存(gc 时间少,次数少,jvm 内存既不能太大,也不能太小)。因此调优的实践本质就是设置 jvm 参数

      1、典型设置

      典型的参数设置: 服务器配置 —> 4cpus,8GB

        1、-Xmx4000m 设置 JVM 堆内存最大值(经验值设置:3500m --- 4000m,内存大小的设置,没有一个固定值,根据业务场景实际情况,根据压力测试运行情况进行调试,在上线后,进行调试)。例如: 对象 1 占用内存 128KB;对象 2 占用内存 300KB

        2、-Xms4000m 设置 JVM 初始化内存(必须和 Xmx 最大内存设置一致,防止内存抖动,损耗性能)

        3、-Xmn2g 设置年轻代大小(eden ,s0 ,s1)

        4、-Xss256k 设置线程堆栈大小,jdk1.5+版本线程堆栈默认 1MB, 相同内存情况下,线程堆栈越小,操作系统有能力创建更多线程,系统性能将会越好;

      查看对象占用JVM堆内存大小:

    RamUsageEstimator.humanSizeOf(seckillGoods)

      然后调整代码的执行命令,设置上面的参数:

    nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

          

       根据压力测试结果(20w 样本),发现 JVM 内存参数设置后,没有任何优化效果(变化),原因就在于在这个业务场景下没有发生频繁的 gc(gc 导致 stw ,stw 最终影响性能);那我们是根据什么指标判断 jvm 调优的参数是合适的,是否能提到调优的效果的呢:

        (1)发生几次 GC ,GC 次数是否减少,是否频繁的发生 GC, 发送 GC 时间

        (2)业务线程执行时间比例 (业务线程执行时间超过 95%, 5%时间 gc 时间,此时不需要调优)

        (3)是否发生 fullgc (fullgc 耗时比较长,性能影响比较大,fullgc 发生次数)

        (4)oom

       2、GC日志

        JVM 在 gc 的时候输出日志,把日志写入文件中,使用相应工具(gceasy.io)对日志进行分析,分析 jvm 堆内存调优的结果是否合适。

    nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

         通过 jvm 相关参数,输出 gc 日志,通过分析 gc 日志判定 gc 的参数设置是否合理;从而给调试 jvm 堆内存设置提供参考依据;

        拿到 gc 日志后,可以在  gceasy.io  网站进行在线分析

        (1)内存使用情况

            用于展示各分代的总内存和最大使用内存。

          

         (2)执行时间对比

          这个是关键的是否需要JVM调优的判断标准,如果业务时间占比大于95%,就无需调优。

          

       

         (3)GC耗时占比

          

         (4)发生GC的时间点和次数

            根据内存分布情况,old 最大使用 157mb , 而在此时却发生了 fullgc ,很明显这是不正常的,必须进行调试,规避不正常的 fullgc

          

         (5)GC统计

          

       3、fullGC问题

        20w 样本测试后,old 区域使用最大值 157mb, old 区域分配的内存是 1.9gb , 却发生了 full gc,这肯定不正常的,原因: metaspaceSize 云数据空间发生了扩展,导致了 fullgc 的发发生;metaspace 发生一次扩容,就会发生一次 fullgc(可以查看gc日志,可以看到元空间占用内存在变大)

    jstat -gcutil 11811
    jstat -gc 11811 2s 3
    java -XX:+PrintFlagsFinal -version | grep MetaspaceSize

          

         根据 metaspace 扩容阀值的大小,看出超过 20m,就会发生第一次扩容(gc日志);

           

         Metaspace 发生了扩容(gc日志):

          

         解决方案: 观察 gc 日志,看 metaspace 最大使用空间是多少,然后把 metaspace 空间大小设置为比这个值大即可;

            

         根 据 上 图 所 示 , metaspace>55.11mb ; metaspace = 256m , 完 全 够 用 的 ;-XX:MaxMetaspaceSize=500m :定义最大的元数据空间,此时如果 metaspace 装不下,就会发生 fullgc ,同时 oom;

    nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

         查看日志优化情况,看 fullgc 是否发生:

           

         可以发现此时 fullgc 消失了,说明解决问题:

          

       4、Yong&old

         年轻代,老年代大小比例的设置根据业务情况进行灵活的设置,无非就是 yong 空间设置大些,尽量让对象在年轻被回收;或者是老年代设置大些,在一些大对象,老年代对象比较多的情况下;

        设置方案: -XX:NewRatio = 4 ,年轻代 : 老年代比值 = 1:4,预测结果: 年轻代空间进一步缩小(更频繁的 yong gc – 耗时少),老年代的空间进一步增大(尽量防止 fullgc 的发生 – 不耗时)

        分配结果: 1、yong : old = 1:4 (4000MB) 800MB:3200MB , yong memory 变得更小了,oldmemory 变得更大了;2、-Xmn2g 直接设置年轻代大小,剩下的就是老年代的;

        修改配置:将Xmn删除(-Xmn2g),新增NewRatio配置项(-XX:NewRatio=4)

    nohup java -Xmx4000m -Xms4000m -XX:NewRatio=4 -Xss256k -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

           

         Yong gc 发生的次数更多了,但是 gc 时间更加快速了,但是总消耗的时间变多了;

        但是这种也不是不能这样设置,这是一个需要权衡的结果,使用场景: 防止发生 fullgc(fullgc 有一些,消耗时间)

          

       5、Eden & s0 & s1

        尽量让对象在年轻代被回收(大多数对象都在年轻代被释放内存)官方推荐设置: eden : s0 : s1 = 8:1:1 设置方式: -XX:SurvivorRatio = 8。

     (二)垃圾回收器组合

      1、吞吐量优先

        并行垃圾回收器:

          年轻代: parNew , Parallel Scavenge

          老年代: Parallel old

        对于吞吐量优先的垃圾回收器: 使用常用组合: ps + po ,此组合是 jdk1.8 默认的垃圾回收器

    nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

      2、响应时间优先

        响应时间优先组合: parNew + CMS 垃圾回收器 ,响应时间优先主要是对 CMS(老年代垃圾回收器)来说的,适用于:老年代发生 fullgc 比较多的情况,且无法避免 fullgc;

        -XX:+UseParNewGC : 年轻代垃圾回收器,并行的垃圾回收器

        -XX:+UseConcMarkSweepGC: 老年代的垃圾回收器,并发的垃圾回收器(业务线程交叉执行)

    nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

      3、G1 组合

      XX:+UseG1GC : 表示使用 g1 垃圾回收器; 使用更加简单,逻辑上分代模型;

    nohup java -Xmx4000m -Xms4000m -Xmn2g -Xss256k -XX:MetaspaceSize=256m -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar jshop.jar --spring.config.addition-location=application.yaml > shop.log 2>&1 &

       可以发现: 垃圾回收次数比较少的,但是总耗时比较长;

           

        

    ------------------------------------------------------------------
    -----------------------------------------------------------
    ---------------------------------------------
    朦胧的夜 留笔~~
  • 相关阅读:
    2021.1.20 学习总结
    2021.1.19 学习总结
    2021.1.18 学习总结
    学习总结13
    学习总结12
    学习总结11
    学习总结10
    ASP.NET网站开发步骤
    学习总结9
    阅读笔记4
  • 原文地址:https://www.cnblogs.com/liconglong/p/15463880.html
Copyright © 2011-2022 走看看