18、案例实战:上亿请求轻松应对,看年轻代垃圾回收如何助力电商性能飞跃!

news2024/11/26 8:49:43
18.1、背景引入

我们通常会通过案例分析,来指导大家如何在不同的场景下,预测系统的内存使用模型。我们需要合理地调整新生代、老年代、Eden和Survivor各个区域的内存大小,然后尽可能地优化参数,以减少新生代对象进入老年代的情况,让这些对象尽可能地在新生代中被回收。

在我们的讨论背景中,我们以电商系统为例。电商系统通常被拆分为多个独立的子系统进行部署,例如商品系统、订单系统、促销系统、库存系统、仓储系统和会员系统等。

我们的案例背景是一个每日处理上亿请求量的电商系统。我们可以推算,这样的系统每天会有多少活跃用户?如果我们假设每个用户平均访问20次,那么上亿的请求量大约需要500万的日活跃用户。

接下来,我们继续推算,这500万的日活跃用户中,有多少人会下订单?如果我们按照10%的付费转化率来计算,那么每天大约有50万人会下订单,也就是每天大约有50万订单。

如果这50万订单集中在每天4小时的高峰期内,那么平均每秒大约只有几十个订单。这可能会让人感觉压力并不大,因为在几十个订单的压力下,我们并不需要过多关注JVM的性能。在这种情况下,新生代的内存每秒只会被占用一部分,新生代会在很长一段时间后才会满,然后通过一次Minor GC,垃圾对象被清理掉,内存空间就被释放出来,几乎没有任何压力。

18.2、特殊的电商大促场景

如果你考虑到特殊的电商大促场景,你的想法可能会有所改变。在平常情况下,许多中小型电商平台的系统压力并不是特别大,高并发情况也相对较少,每秒几千的并发压力可能就已经算是高峰压力了。然而,一旦遇到大促场景,比如双11等,情况就会发生显著变化。

设想一下,在类似双11的节日里,零点一到,许多人都在等待大促的开始,准备疯狂购物。在这个时候,可能在大促开始的短短10分钟内,瞬间就会产生50万订单。那么,在这个时间段内,每秒可能会有接近1000的下单请求。因此,我们需要针对这种大促场景,对订单系统的内存使用模型进行深入分析。

18.3、了解大促期间您需要的机器军团规模

为了应对大促期间的瞬时下单压力,订单系统需要部署几台机器呢?

基本上可以按3台来算,即每台机器每秒需要承受300个下单请求。这个配置是非常合理的,而且需要假设订单系统部署的就是最普通的标配4核8G机器。

从机器本身的CPU资源和内存资源角度来看,抗住每秒300个下单请求是没问题的。但是问题就在于需要对JVM有限的内存资源进行合理的分配和优化,包括对垃圾回收进行合理的优化,让JVM的GC次数尽可能最少,而且尽量避免Full GC,这样可以尽可能减少JVM的GC对高峰期的系统性能的影响。

18.4、如何精确预测大促期间订单系统的内存需求?

根据背景信息,我们需要对订单系统的内存使用进行模型预估。我们假设系统每秒处理300个下单请求,这个数值与实际生产环境相近。

每个订单的处理是相对耗时的,涉及多个接口调用,因此每秒处理100~300个订单请求是合理的。我们以每个订单1KB的大小进行估算,那么300个订单将产生约300KB的内存消耗。

考虑到每个订单还会关联其他业务对象,如订单条目、库存、促销和优惠券等,通常单个订单的开销需要放大10倍至20倍。此外,除了下单操作外,订单系统还包含其他与订单相关的操作,如订单查询等,所以整体开销可以再扩大10倍。

综上所述,每秒钟的内存开销大约为:300KB × 20 × 10 = 60MB。然而,一旦这300个订单处理完毕,这些相关对象就会失去引用,进入可回收状态,因此在一秒钟后,这60MB的内存可以被视为垃圾进行回收。

大家看下图:
在这里插入图片描述

18.5、如何巧妙分配内存来提升性能?

假设我们有一台4核8G的计算机,通常我们会将JVM内存设置为4G,剩余的内存则留给操作系统等其他程序使用。在分配JVM内存时,我们可以将堆内存设置为3G,其中新生代和老年代各占1.5G。每个Java线程的虚拟机栈大小为1M,因此如果有几百个线程,大约需要几百M的内存。此外,还需要为永久代分配256M的内存。这样,基本上就分配了4G的内存。

在使用JVM时,还需要设置一些必要的参数,例如开启“-XX:HandlePromotionFailure”选项。不过,这个参数在JDK 1.6之后已经被废弃,因此在生产环境中一般不会设置这个参数。在JDK 1.6之后,只要满足以下两个条件之一,就可以直接进行Minor GC,而不需要提前触发Full GC:1. “老年代可用空间”> “新生代对象总和”;2. “老年代可用空间”> “历次Minor GC升入老年代对象的平均大小”。

因此,如果我们使用的是JDK 1.7或JDK 1.8,那么JVM参数可以保持如下设置,后面也不再加入“-XX:HandlePromotionFailure”参数:

“-Xms3072M -Xmx3072M -Xmn1536M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M”,此时JVM内存入下图所示。
在这里插入图片描述

接着就很明确了,订单系统的系统程序在大促期间不停的运行,每秒处理300个订单,都会占据新生代60MB的内存空间
但是1秒过后这60MB对象都会变成垃圾,那么新生代1.5G的内存空间大概需要25秒就会占满,如下图。
在这里插入图片描述

在25秒后,系统将执行Minor GC。由于设置了"-XX:HandlePromotionFailure"选项,因此需要进行的检查主要是比较“老年代可用空间大小”和“历次Minor GC后进入老年代对象的平均大小”。在初始阶段,这个检查通常是可以通过的。

因此,Minor GC会直接运行,可以回收掉99%的新生代对象。这是因为除了最近一秒钟的订单请求仍在处理中,大部分订单已经完成处理,所以此时可能存活的对象大约为100MB。

然而,这里出现了一个问题。如果"-XX:SurvivorRatio"参数的默认值为8,那么此时新生代中的Eden区大约占用了1.2GB内存,每个Survivor区占用了150MB内存。如下图。
在这里插入图片描述

所以Eden区1.2GB满了就要进行Minor GC了,因此大概只需要20秒,就会把Eden区塞满,就要进行Minor GC了。
然后GC后存活对象在100MB左右,会放入S1区域内。如下图。
在这里插入图片描述

当Eden区的1.2GB空间被填满时,就会触发一次Minor GC(垃圾回收)。这个过程大约需要20秒。在Minor GC执行之后,那些仍然存活的对象,其大小约在100MB左右,会被移动到S1区域,如下图。
在这里插入图片描述

此时JVM参数如下:
“-Xms3072M -Xmx3072M -Xmn1536M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:SurvivorRatio=8”

18.6、如何优雅地解决Survivor空间不足?

在对JVM进行优化时,首先需要关注的一个问题是,通过估算判断新生代的Survivor区是否足够。

根据上述逻辑,如果每次新生代垃圾回收大约占用100MB,甚至可能超过150MB,那么在Minor GC之后,对象无法放入Survivor区的情况可能会经常发生,这会导致对象频繁地进入老年代。

此外,即使在Minor GC后的对象少于150MB,但如果是100MB的对象进入Survivor区,由于这是一批同龄的对象,它们会直接超过Survivor区空间的50%,这也可能导致对象进入老年代。

因此,按照我们这个模型来看,Survivor区域显然是不足的。

在这里,建议调整新生代和老年代的大小。对于这种普通业务系统,显然大部分对象都是短生命周期的,不应该频繁进入老年代,也没有必要为老年代分配过大的内存空间。首先应该尽量让对象留在新生代中。

因此,可以考虑将新生代调整为2GB,老年代调整为1GB。这样,Eden区将为1.6GB,每个Survivor区将为200MB。如下图。
在这里插入图片描述

在这个阶段,我们可以通过增大Survivor区域的大小,有效地降低新生代垃圾回收(GC)后存活对象无法放入Survivor区域的问题,或者解决同龄对象超过Survivor区域50%的问题。这样做可以显著降低新生代对象被晋升到老年代的几率。

在这种情况下,Java虚拟机(JVM)的参数设置如下:

-Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:SurvivorRatio=8

对于任何系统,首先需要做的是进行内存使用模型的预估和合理分配内存,尽量确保每次Minor GC后的对象都能留在Survivor区域,避免它们被晋升到老年代。这是优化的首要步骤。

18.7、新生代如何巧妙躲过垃圾回收进入老年代?

众所周知,当对象在Minor GC后无法放入Survivor区时,它们会被送入老年代。此外,如果某些对象连续躲过15次垃圾回收,它们也会自动晋升至老年代。

根据上述内存运行模型,通常情况下,每20多秒会触发一次Minor GC。按照默认参数“-XX:MaxTenuringThreshold”的值15,如果一个对象连续躲过15次GC,意味着它在新生代中已经停留了几分钟。在这种情况下,将其晋升至老年代是合理的。

有些博客建议提高这个参数,例如将其增加到20或30。然而,这种观点并不正确。在考虑调整该参数时,必须结合系统的运行模型。如果一个对象在几次GC后仍然无法被回收,说明它可能是系统中长期存活的核心业务逻辑组件,如使用@Service、@Controller等注解标注的组件。这类对象通常很少,一个系统中最多只有几十MB。

因此,提高“-XX:MaxTenuringThreshold”参数的值并没有太大意义。让这些对象在新生代中多停留几分钟又能如何呢?

实际上,你甚至可以降低这个参数的值,例如将其降低到5,这意味着如果一个对象躲过5次Minor GC,在新生代中停留超过1分钟,就尽快将其晋升至老年代,避免占用过多新生代内存。

总之,对于这个参数,务必结合你的系统具体运行模型来进行调整。

请记住,JVM没有通用的最佳参数设置,但有一套通用的分析和优化方法。当前的JVM参数如下:

-Xms3072M -Xmx3072M -Xmn2048M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5
18.8、究竟什么决定了对象直达老年代?

在计算机编程中,有一个逻辑概念是大对象可以直接进入老年代。这是因为大对象通常表示它们需要长期存活和使用。例如,在Java虚拟机(JVM)中,可能会缓存一些数据,这通常可以根据系统中是否创建了大对象来决定。

然而,一般来说,将大对象的阈值设置为1MB就足够了。因为超过1MB的大对象非常罕见。如果存在这样的大对象,可能是因为你提前分配了一个大数组、大List等用于存放缓存数据的数据结构。此时JVM参数如下:

-Xms3072M -Xmx3072M -Xmn2048M -Xss1M  -XX:PermSize=256M -XX:MaxPermSize=256M  -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 -XX:PretenureSizeThreshold=1M
18.9、正确配置JVM垃圾回收器

同时,请大家不要忘记设置垃圾回收器。对于新生代,我们使用ParNew,而对于老年代,我们使用CMS。以下是相应的JVM参数:

-Xms3072M -Xmx3072M -Xmn2048M -Xss1M  -XX:PermSize=256M -XX:MaxPermSize=256M  -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5 -XX:PretenureSizeThreshold=1M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC

ParNew垃圾回收器的核心参数主要是新生代的内存大小,以及Eden和Survivor的比例。只要这些参数设置得当,就可以避免在Minor GC后,对象无法放入Survivor而进入老年代,或者在动态年龄判定后进入老年代。这样,只要给新生代的Survivor留出足够的空间,Minor GC通常就不会有问题。

然后,根据你的系统运行模型,合理设置-XX:MaxTenuringThreshold,使得长期存活的对象能够尽快进入老年代,而不是一直在新生代中停留。

这样,我们就得到了一个初步优化的JVM参数,它已经结合了你的业务需求。明天,我们将继续通过案例来分析老年代的垃圾回收和参数优化方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1669291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

An 2024下载

An2024下载: 百度网盘下载https://pan.baidu.com/s/1cQQCFL16OUY1G6uQWgDbSg?pwdSIMS Adobe Animate 2024,作为Flash技术的进化顶点,是Adobe匠心打造的动画与交互内容创作的旗舰软件。这款工具赋予设计师与开发者前所未有的创意自由&#x…

火绒安全原理、用法、案例和注意事项

火绒安全是一款功能强大的安全软件,它采用了先进的安全技术和算法,通过实时监测、恶意代码识别、防火墙功能、沙箱技术和网络保护等多种手段,为用户提供全面的计算机安全防护。 1.为什么选用火绒安全? 火绒安全是一款优秀的安全软…

用lobehub打造一个永久免费的AI个人助理

Lobe Chat是一个开源的高性能聊天机器人框架,它被设计来帮助用户轻松创建和部署自己的聊天机器人。这个框架支持多种智能功能,比如语音合成(就是让机器人能说话),还能理解和处理多种类型的信息,不仅限于文字…

AI图书推荐:用GPT-4进行预测分析的实用指南

《用GPT-4进行预测分析的实用指南》(A Practical Guide to Predictive Analytics with GPT-4)为读者提供了一个全面的指南,介绍了如何利用GPT-4的强大预测能力,从理解预测分析的基础,到掌握GPT-4的使用,再到…

基于yolov5+gradio目标检测演示系统设计

YOLOv5与Gradio:目标检测可视化展示的新篇章 随着人工智能技术的深入发展,目标检测已成为现代智能应用中的一项关键技术。YOLOv5,作为目标检测领域的杰出代表,凭借其出色的实时性和准确性,赢得了广泛的认可和应用。而…

电力场景设备漏油检测数据集VOC+YOLO格式338张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):338 标注数量(xml文件个数):338 标注数量(txt文件个数):338 标注类别…

数据缓存,可以尝试RocksDB了

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 个人IP:shigen shigen在最近的学习中,接触到了一款新的缓存数据库RocksDB&#xff…

SQL语句优化技巧

目录 1、sql语句规范 2、sql语句优化 1、sql语句规范 MySQL在Linux系统下数据库名,表名,存储过程名,函数名称,触发器名称等区分大小写,列名不区分大小写,原因是这些操作系统下文件名称区分大小写。 MySQL…

LNMP 环境下 Nginx 1.26.0 开启 HTTP/3 QUIC 支持

前几天 Nginx 1.26.0 主线版发布了,明月总算抽出时间更新了,那么自然的也要尝试一下开启 HTTP/3 QUIC 支持了,今天就给大家分享一下。对于我们的网站来说开启 HTTP/3 QUIC 最大的好处是页面载入速度的提升,尤其是在支持 HTTP/3 QU…

安卓模拟器怎么修改ip地址

最近很多老铁玩游戏的,想多开模拟器一个窗口一个IP,若模拟器窗口开多了,IP一样会受到限制,那么怎么更换自己电脑手机模拟器IP地址呢,今天就教大家一个修改模拟器IP地址的方法!废话不多说,直接上…

牛客NC363 开锁【中等 BFS Java/Go/PHP】

题目 题目链接: https://www.nowcoder.com/practice/e7cbabbf7e0a41ec98055ee5f3d33bbe https://www.lintcode.com/problem/796 思路 Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改&#x…

文件系统(未打开的文件)

之前我们讲述的一些文件操作都是在文件被打开的基础上的,因为用户想要对某个文件做操作的话,这个文件一定是被打开的,也就是一定是内存级的文件。 但是有的没有被操作的文件,是在磁盘中的,我们的笔记本是在SSD中&…

Debian Linux 下给Nginx 1.26.0 编译增加Brotli算法支持

明月发现参考【给Nginx添加谷歌Brotli压缩算法支持】一文给出的方法,在Debian Linux 12.5下就一直编译失败,主要的错误是因为文件缺失,在专门又安装了apt-get install libbrotli-dev的依赖库后依然会因为文件缺失无法编译完成,就这…

JCR一区 | Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预测

JCR一区 | Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预测 目录 JCR一区 | Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 Matlab实现1D-2D-GASF-CNN-BiLSTM-MATT的多通道输入数据分类预…

Postman基础功能-常见类型的接口请求

天空灰暗到一定程度,星辰就会熠熠生辉。大家好,之前给大家分享了关于 Postman 工具的介绍以及安装,在当今数字化的时代,接口请求在软件开发和系统集成中扮演着至关重要的角色。而 Postman 作为一款强大且广受认可的接口测试工具&a…

信息系统项目管理师0105:项目评估与决策(7项目立项管理—7.3项目评估与决策)

点击查看专栏目录 文章目录 7.3项目评估与决策1.评估依据2.评估的程序3.项目评估的内容4.项目评估报告内容大纲记忆要点总结7.3项目评估与决策 项目评估指在项目可行性研究的基础上,由第三方(国家、银行或有关机构)根据国家颁布的政策、法规、方法、参数和条例等,从国民经济…

Java | Leetcode Java题解之第77题组合

题目&#xff1a; 题解&#xff1a; class Solution {List<Integer> temp new ArrayList<Integer>();List<List<Integer>> ans new ArrayList<List<Integer>>();public List<List<Integer>> combine(int n, int k) {List&l…

[Spring Cloud] (7)gateway防重放拦截器

文章目录 简述本文涉及代码已开源Fir Cloud 完整项目防重放防重放必要性&#xff1a;防重放机制作用&#xff1a; 整体效果后端进行处理 后端增加防重放开关配置签名密钥 工具类防重放拦截器 前端被防重放拦截增加防重放开关配置请求头增加防重放签名处理防重放验证处理函数bas…

信息系统项目管理师0104:详细可行性研究(7项目立项管理—7.2项目可行性研究—7.2.3详细可行性研究)

点击查看专栏目录 文章目录 7.2.3详细可行性研究1.详细可行性研究的依据2.详细可行性研究的原则3.详细可行性研究的方法4.详细可行性研究的内容5.详细可行性研究报告记忆要点总结7.2.3详细可行性研究 详细可行性研究是在项目决策前对与项目有关的技术、经济、

14.CAS原理

文章目录 CAS原理1.什么是CAS2.Unsafe类中的CAS方法2.1.获取UnSafe实例2.2.调用UnSafe提供的CAS方法2.3.调用Unsafe提供的偏移量相关2.4.CAS无锁编程2.4.1.使用cas进行无锁安全自增案例 CAS原理 由于JVM的synchronized重量级锁设计操作系统内核态下的互斥锁的使用&#xff0c;其…