jvm性能调优 - 07线上应用部署JVM实战_栈内存与永久代预估与设置

简介: jvm性能调优 - 07线上应用部署JVM实战_栈内存与永久代预估与设置

Pre

上一篇给大家基于案例分析了一下,如果我们准备上线一个新的系统,如何根据这个系统未来预估的业务量,访问量,去推算这个系统每秒种的并发量,然后推算每秒钟的请求对内存空间的占用,进而推算出整个系统运行期间的JVM内存运转模型。

然后基于这个推算出来的JVM内存运转模型,再接着去在系统上线前就选择一个合理的机器配置,要多大内存的机器,另外给JVM堆内存空间一个合理的大小。

其实这是一项非常基础的技能,因为对于大厂工程师,每次上线一个新的系统,他可能上线就会面临很大的访问压力

所以必须要学会合理预估内存压力,然后选择对应的机器配置,并且给出合理的内存大小 。



基于案例,说说不合理设置内存的反面示例

说的是一个正面的例子,即如何合理的设置内存大小。

今天来说一个反面的不合理设置内存大小导致的问题, 比如现在我们假设一个前提,就是支付系统因为没有经过合理的内存预估,所以直接选用了1台2核4G的虚拟机来部署了线上系统,而且就只用了一台机器

然后线上JVM给的堆内存大小,仅仅就只有1G,扣除老年代之后,新生代其实就几百MB的内存空间,大家看下图。


好了,接着我们还是用相同的业务压力,就是每天100万交易,高峰期每秒大概100笔支付交易,对应核心的支付订单对象有100个创建出来,每个支付订单对象占据500左右的字节大小,总共就是50kb左右。

然后一笔交易要1秒来处理,所以这100个对象在新生代中存在1秒的期间会被人引用,是无法被回收的。

而且我们之前说过一个全局预估的思路,从核心的支付订单对象扩展开来,拓展到系统里其他的对象中去,起码可以把内存占用扩大了10倍~20倍

比如我们就扩大个20倍好了,那么说明1秒之内,总共会创建出来大概1MB左右的对象,无法被回收。


大促期间,流量激增

其实按照估算出来的内存压力,你这么小的新生代在系统正常运行的情况下,其实还不算什么大问题。

因为每秒新增1MB对象,然后几百秒过后,新生代快满了,自然就会触发Minor GC,回收掉里面99%的垃圾对象。

你要是内存那么小,最多就是发现系统每隔几分钟略微卡顿一下,因为这个时候在进行垃圾回收,会影响系统性能。

但是现在我们假设,如果你的电商系统搞大促活动呢?

一般搞大促活动,很可能导致你的压力瞬间增大10倍,因为平时不来你网站的人,今天都来了。

此时可能会发现,每秒钟你的支付系统不是100笔订单了,可能是每秒钟上千笔订单。

这个时候你的系统压力本身就会很大了,不光是内存,尤其是线程资源、CPU资源,都会几乎打满。内存就更是岌岌可危了。


少数请求需要几十秒处理,导致老年代内存占用变大

咱们就针对内存来分析一下。

现在假设你每秒1000笔交易,那么每秒钟系统对内存的占用增加到10MB以上

我们甚至可以再大胆一点,预估每秒对内存占用达到几十MB,甚至上百MB也可以,因为毕竟大促时流量激增,就一切围绕这来预估。

而且最可怕的一点是,可能你每秒过来的1000笔交易,不再是1秒就可以处理完毕了,因为压力骤增,会导致你的系统性能下降,可能偶尔会出现每个请求处理完毕需要几秒钟,甚至几十秒的时间。

此时我们看下图可能出现什么问题,假设你的新生代里已经积压了很多的数据,都快满了。


然后呢,此时内存里有比如几十MB的对象都被人引用着,因为少数请求突然处理的特别慢。

为什么会处理特别慢?因为压力太大,导致系统性能太差了,如下图。


这个时候,如果你要再次在新生代里分配对象,那么是不是会导致一次Minor GC去回收新生代?

没错,但是可能回收掉大量的对象之后,那少数几十MB的对象还在,因为少数请求特别的慢。

然后很快新生代继续被填满,再次触发Minor GC,然后少数几十MB的对象还在,此时多次之后后,就会被转移到老年代去,如下图。



老年代对象越来越多导致频繁垃圾回收

那么大家思考一下,上述流程如果反复来多次,就是时不时有少数请求特别慢,创建的对象在新生代反复多次没法被回收,然后就会被弄到老年代去

然后后续处理完之后,老年代里的对象就没人引用了,成为了垃圾对象。

经常重复这个流程,老年代里的垃圾对象,是不是就会越来越多?

一旦老年代的垃圾对象越来越多,迟早会满,然后就会触发老年代的垃圾回收,而且这个老年代被占满的频率还很快,可能就会频繁触发老年代的垃圾回收。

大家要知道,老年代的垃圾回收速度是很慢的,后面我们分析。

但是在上述场景下,我们基本可以分析出来,如果你不合理的设置内存,就会导致新生代内存不充足,然后导致很多对象不停的迁移到老年代去,最后导致老年代也要不停的进行垃圾回收。

最后这频繁的垃圾回收,就会极大的影响系统的性能。


小结

通过一个支付系统内存设置过小,然后突发巨大的流量压力,突发的性能抖动,最后导致很多对象长期在新生代被人引用,无法被回收,最后持续进入老年代,最后触发老年代内存都频繁占满,然后老年代都频繁被垃圾回收。

所以大家更能从反面体会到,不合理的预估 业务系统压力,不合理的设置内存大小,就可能会导致很大的问题。


如何合理设置永久代大小?

话说回来,如何合理设置永久代大小呢?

其实一般永久代刚开始上线一个系统,没太多可以参考的规范,但是一般你设置个几百MB,大体上都是够用的

因为里面主要就是存放一些类的信息,后面分析什么样的系统容易出现永久代内存溢出。


如何合理设置栈内存大小

其实这个栈内存大小设置,一般也不会特别的去预估和设置的,一般默认就是比如512KB到1MB,就差不多够了

这就是每个线程自己的栈内存空间,用来存放线程执行方法期间的各种布局变量的。后面介绍栈内存什么时候会发生内存溢出。


思考

自己负责的系统的内存压力,然后就是JVM内存大小是否合理,如果业务暴增100倍,是否会有内存问题。

自己画出核心业务流程图,然后一点点去分析,这是一个非常重要的技能。 其实JVM实战技能里的第一步,就是合理预估系统内存压力,合理设置JVM内存大小。


相关文章
|
3月前
|
监控 Java 测试技术
JVM 性能调优 及 为什么要减少 Full GC
JVM 性能调优 及 为什么要减少 Full GC
94 4
|
12天前
|
Kubernetes Java 编译器
解锁极致性能:Quarkus如何让JVM应用调优变得前所未有的简单与高效!
Quarkus是一款专为GraalVM和OpenJDK设计的Kubernetes Native Java框架,采用AOT编译技术将Java应用转化为本地代码,大幅提升启动速度与运行效率。它简化了性能调优流程,如自动优化垃圾回收、类加载、内存管理及线程管理等,使开发者无需深入理解JVM细节即可轻松提升应用性能。与传统JVM应用相比,Quarkus显著降低了性能调优的复杂度。
47 2
|
3月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
|
3月前
|
运维 监控 Java
(十)JVM成神路之线上故障排查、性能监控工具分析及各线上问题排错实战
经过前述九章的JVM知识学习后,咱们对于JVM的整体知识体系已经有了全面的认知。但前面的章节中,更多的是停留在理论上进行阐述,而本章节中则更多的会分析JVM的实战操作。
|
2月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
2月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用
|
3月前
|
缓存 监控 Java
Java虚拟机(JVM)性能调优实战指南
在追求软件开发卓越的征途中,Java虚拟机(JVM)性能调优是一个不可或缺的环节。本文将通过具体的数据和案例,深入探讨JVM性能调优的理论基础与实践技巧,旨在为广大Java开发者提供一套系统化的性能优化方案。文章首先剖析了JVM内存管理机制的工作原理,然后通过对比分析不同垃圾收集器的适用场景及性能表现,为读者揭示了选择合适垃圾回收策略的数据支持。接下来,结合线程管理和JIT编译优化等高级话题,文章详细阐述了如何利用现代JVM提供的丰富工具进行问题诊断和性能监控。最后,通过实际案例分析,展示了性能调优过程中可能遇到的挑战及应对策略,确保读者能够将理论运用于实践,有效提升Java应用的性能。 【
164 10
|
3月前
|
JSON Java BI
一次Java性能调优实践【代码+JVM 性能提升70%】
这是我第一次对系统进行调优,涉及代码和JVM层面的调优。如果你能看到最后的话,或许会对你日常的开发有帮助,可以避免像我一样,犯一些低级别的错误。本次调优的代码是埋点系统中的报表分析功能,小公司,开发结束后,没有Code Review环节,所以下面某些问题,也许在Code Review环节就可以避免。
149 0
一次Java性能调优实践【代码+JVM 性能提升70%】
|
3月前
|
弹性计算 运维 Java
Serverless 应用引擎使用问题之JVM进行垃圾回收时重启,该如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
|
2月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。