jvm性能调优实战 - 26一个每秒10万并发的系统如何频繁发生Young GC的

简介: jvm性能调优实战 - 26一个每秒10万并发的系统如何频繁发生Young GC的

业务简介

一个服务于百万级商家的BI系统。

简单来说,比如你是一个平台,然后有数十万甚至上百万的商家在你的平台上做生意,会使用你的这个平台系统

此时一定会产生大量的数据,然后基于这些数据我们需要为商家提供一些数据报表,比如:每个商家每天有多少访客?有多少交易?付费转化率是多少?

当然实际情况会比这个简单几句话复杂很多,我们这里就简单说个概念而已。所以此时就需要一套BI系统

所谓BI,英文全称是“Business Intelligence”,也就是“商业智能” 。

类似这样的一个BI系统,大致的运行逻辑如下所示,首先从我们提供给商家日常使用的一个平台上会采集出来很多商家日常经营的数据,如下图所示。

接着就可以对这些经营数据依托各种大数据计算平台,比如Hadoop、Spark、Flink等技术进行海量数据的计算,计算出来各种各样的数据报表,如下图所示。

然后我们需要将计算好的各种数据分析报表都放入一些存储中,比如说MySQL、Elastcisearch、HBase都可以存放类似的数据,如下图所示。

最后一步,就是基于MySQL、HBase、Elasticsearch中存储的数据报表,基于Java开发出来一个BI系统,通过这个系统把各种存储好的数据暴露给前端,允许前端基于各种条件对存储好的数据进行复杂的筛选和分析,如下图所示。


系统初期

一开始系统上线大概就少数商家在使用,比如就几千个商家。

所以刚开始系统部署的非常简单,就是用几台机器来部署了上述的BI系统,机器都是普通的4核8G的配置,然后在这个配置之下,一般来说给堆内存中的新生代分配的内存都在1.5G左右,Eden区大概也就1G左右的空间


技术痛点:实时自动刷新报表 + 大数据量报表

其实刚开始,在少数商家的量级之下,这个系统是没多大问题的,运行的非常良好,但是问题恰恰就出在突然使用系统的商家数量开始暴涨的时候。

突然使用系统的商家开始越来越多,比如给大家举个例子,当商家的数量级达到几万的时候。

此时要给大家说明一个此类BI系统的特点,就是在BI系统中有一种数据报表,他是支持前端页面有一个JS脚本,自动每隔几秒钟就发送请求到后台刷新一下数据的,这种报表称之为“实时数据报表”,如下图所示。

那么大家可以设想一下,假设仅仅就几万商家作为你的系统用户,很可能同一时间打开那个实时报表的商家就有几千个

然后每个商家打开实时报表之后,前端页面都会每隔几秒钟发送请求到后台来加载最新数据,基本上会出现你BI系统部署的每台机器每秒的请求会达到几百个,我们假设就是每秒500个请求吧。

然后每个请求会加载出来一张报表需要的大量数据,因为BI系统可能还需要针对那些数据进行内存中的现场计算加工一下,才能返回给前端页面展示。

根据我们之前的测算,每个请求大概需要加载出来100kb的数据进行计算,因此每秒500个请求,就需要加载出来50MB的数据到内存中进行计算,如下图所示。


没什么大影响的频繁Young GC

其实大家都已经发现上述系统的问题了,在上述系统运行模型下,基本上每秒会加载50MB的数据到Eden区中,只要区区200s,也就是3分钟左右的时间,就会迅速填满Eden区,然后触发一次Young GC对新生代进行垃圾回收。

当然1G左右的Eden进行Young GC其实速度相对是比较快的,可能也就几十ms的时间就可以搞定了

所以之前也分析过,其实对系统性能影响并不大。而且上述BI系统场景下,基本上每次Young GC后存活对象可能就几十MB,甚至是几MB。

所以如果仅仅只是这样的话,那么大家可能会看到如下场景,BI系统运行几分钟过后,就会突然卡顿个10ms,但是对终端用户和系统性能几乎是没有影响的,如下图。


提升机器配置:运用大内存机器

针对这样的一套系统,后来随着越来越多的商家来使用,并发压力越来越大,甚至高峰期会有每秒10万的并发压力

大家想想,如果还是用4核8G的机器来支撑,那么可能需要部署上百台机器来抗住每秒10万的高并发压力。

所以一般针对这种情况,我们会提升机器的配置,本身BI系统就是非常吃内存的系统,所以我们将部署的机器全面提升到了16核32G的高配置机器上去。每台机器可以抗个每秒几千请求,此时只要部署比如二三十台机器就可以了。

但是此时问题就来了,大家可以想一下,如果要是用大内存机器的话,那么新生代至少会分配到20G的大内存,Eden区也会占据16G以上的内存空间,此时如下图所示。

此时每秒几千请求的话,每秒大概会加载到内存中几百MB的数据,那么大概可能几十秒,甚至1分钟左右就会填满Eden区,会就需要执行Young GC。

此时Young GC要回收那么大的内存,速度会慢很多,也许此时就会导致系统卡顿个几百毫秒,或者1秒钟,如下图所示。

那么你要是系统卡顿时间过长,必然会导致瞬间很多请求积压排队,严重的时候会导致线上系统时不时出现前端请求超时的问题,就是前端请求之后发现一两秒后还没返回就超时报错了。


用G1来优化大内存机器的Young GC性能

所以当时对这个系统的一个优化,就是采用G1垃圾回收器来应对大内存的Young GC过慢的问题

对G1设置一个预期的GC停顿时间,比如100ms,让G1保证每次Young GC的时候最多停顿100ms,避免影响终端用户的使用。

此时效果是非常显著的,G1会自动控制好在每次Young GC的时候就回收一部分Region,确保GC停顿时间控制在100ms以内

这样的话,也许Young GC的频率会更高一些,但是每次停顿时间很小,这样对系统影响就不大了。


小结

本文用一个案例,其实就想给大家说明一个问题,那就是通常Young GC哪怕发生的频繁一些,其实一般都对系统造成不了太大的影响

只有在你机器内存特别大的时候,要注意Young GC也可能会导致比较长时间的停顿,此时针对大内存机器通常建议采用G1垃圾回收器。


思考

去想办法看看自己线上系统:

  • 多长时间发生一次Young GC?
  • Young GC耗时多久?

然后你觉得它对你的系统影响大吗


相关文章
|
7天前
|
算法 Java
Java垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一种自动内存管理机制,用于在运行时自动回收不再使用的对象所占的内存空间
【6月更文挑战第18天】Java的GC自动回收内存,包括标记清除(产生碎片)、复制(效率低)、标记整理(兼顾连续性与效率)和分代收集(区分新生代和老年代,用不同算法优化)等策略。现代JVM通常采用分代收集,以平衡性能和内存利用率。
33 3
|
13天前
|
运维 Java Shell
手工触发Full GC:JVM调优实战指南
本文是关于Java应用性能调优的指南,重点介绍了如何使用`jmap`工具手动触发Full GC。Full GC是对堆内存全面清理的过程,通常在资源紧张时进行以缓解内存压力。文章详细阐述了Full GC的概念,并提供了两种使用`jmap`触发Full GC的方法:通过`-histo:live`选项获取存活对象统计信息,或使用`-dump`选项生成堆转储文件以分析内存状态。同时,文中也提醒注意手动Full GC可能带来的性能开销,建议在生产环境中谨慎操作。
|
3天前
|
监控 算法 Java
JVM调优-简介(一)
JVM调优-简介(一)
5 0
|
18天前
|
Java 应用服务中间件 Linux
Tomcat 调优及 JVM 参数优化
Tomcat 调优及 JVM 参数优化
|
19天前
|
JSON 监控 Java
编写电脑监控软件的Groovy脚本:JVM生态系统的整合与扩展
使用Groovy编写脚本监控Java虚拟机(JVM)的健康状况,包括内存使用和CPU利用率。脚本可自动将数据提交至指定网站,确保及时发现系统问题,防止服务中断。通过结合Runtime和OperatingSystemMXBean类获取系统信息,利用Groovy的HTTP客户端库POST数据到监控网站,实现高效稳定的系统监控。
54 0
|
25天前
|
存储 算法 Java
JVM性能调优:内存模型及垃圾收集算法
JVM性能调优:内存模型及垃圾收集算法
30 0
|
1天前
|
存储 Java C++
Java虚拟机(JVM)在执行Java程序时,会将其管理的内存划分为几个不同的区域
【6月更文挑战第24天】Java JVM管理内存分7区:程序计数器记录线程执行位置;虚拟机栈处理方法调用,每个线程有独立栈;本地方法栈服务native方法;Java堆存储所有对象实例,垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息;运行时常量池存储常量;直接内存不属于JVM规范,通过`java.nio`手动管理,不受GC直接影响。
11 5
|
1天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
9 2
|
5天前
|
监控 算法 Java
Java虚拟机(JVM)使用多种垃圾回收算法来管理内存,以确保程序运行时不会因为内存不足而崩溃。
【6月更文挑战第20天】Java JVM运用多种GC算法,如标记-清除、复制、标记-压缩、分代收集、增量收集、并行收集和并发标记,以自动化内存管理,防止因内存耗尽导致的程序崩溃。这些算法各有优劣,适应不同的性能和资源需求。垃圾回收旨在避免手动内存管理,简化编程。当遇到内存泄漏,可以借助VisualVM、JConsole或MAT等工具监测内存、生成堆转储,分析引用链并定位泄漏源,从而解决问题。
16 4
|
12天前
|
算法 安全 Java
JVM系列4-垃圾收集器与内存分配策略(二)
JVM系列4-垃圾收集器与内存分配策略(二)
20 0
JVM系列4-垃圾收集器与内存分配策略(二)