负载均衡架构配置(JVM/GC分析与调优)

少年已老

转载:https://blog.csdn.net/qq_3761...
负载均衡架构配置

前期的项目中出问题主要都是代码层,代码层最容易出问题就是死锁,堆内存溢出,或者设置过小
判断堆溢出一般两种方案:
  • 1.对比

           可以用一个文件和跑完之后的文件做对比,看是不是有增长
       
    
  • 2.在文件里面设置,如果有outofmemory,会记录到这个文件里面去

JVM/GC分析与调优

jvm除了堆之外,我们将jvm的目的是谁用了jvm?
是tomcat,我们分析jvm,就相当于分析tomcat了。
tomcat两种级别:

  • 1.tomcat本身自己的设置:
  • 2.jvm

       1.堆,内存的设置
       2.线程的死锁
       3.GC
    

本次主要讲:GC和tomcat本身的设置,还有tomcat前面的nginx
手动执行垃圾回收机制。
在这里插入图片描述

一般代码不出现打的问题,是不需要调GC的。一般是通过GC的现象看代码的问题。临时优化的时候是可以用的

GC分为两个:youngGC和fullGC
Young GC:回收年轻态的
在这里插入图片描述

Full GC:回收年老态的
在这里插入图片描述

如果把对象比作人的话,也是有生命周期的
在这里插入图片描述

幼儿期(Young GC)--->年轻态(S0,S1幸存区,存活区)--->年老区
幼儿期:最容易消亡的,这个时期会频繁发生Young GC。回收的最快
年轻态:大量对象都要经历的过程,如果这个对象一直被使用的话,会把上一个时期的转到这个阶段里面来S0,S1
年老区:如果年轻态阶段的对象还是一直有人使用的话,会转到这个阶段。回收的最慢

如果jvm的资源给GC的话,是不会处理业务请求的

堆溢出是因为对象一直在产生,一直存活,堆在了old区,对象产生的速度比GC都快。越来越多,就会溢出了

fullGC如果太大,一次GC就会花太多的时间。如果太小,会过于频繁。
如果代码写的好的话,不好到oldGC。在youngGC就被清空掉了。因为jvm的资源给GC的话,是不会处理业务请求的

jmap -heap 23816

在这里插入图片描述

jstat -gc 23816 1000 5(1000:毫秒 5 次数)

在这里插入图片描述

S0C:S0区容量(S1区相同,略)
S0U:S0区已使用
EC:E区容量
EU:E区已使用
OC:老年代容量
OU:老年代已使用
PC:Perm容量
PU:Perm区已使用
YGC:Young GC(Minor GC)次数
YGCT:Young GC总耗时
FGC:Full GC次数
FGCT:Full GC总耗时
GCT:GC总耗时

注意事项:

Jvm堆大小=年轻代+年老代
年轻代 = 年轻代-1+S0+S1 注意 年轻代-1、S0、S1三者是实际是动态调整的,总和是年轻代
Java的阻塞式的线程模型基本上可以抛弃了,目前成熟的NIO框架也比较多了。阻塞式IO带来的问题是
线程数量的线性增长,而NIO则可以转换成为常数线程。因此,对于服务端的应用而言,NIO还是不错
的选择

不是说GC的话是微调的,主要是代码
正常是不要调的

内存的溢出是系统级别的(swap交换区,si,so。最好都是0)
堆溢出一般是进程级别的(tomcat)

我们一般就调3个东西

1.堆(配置文件里面)
2.年轻态和old关系(一般是1:3)
3.old区的执行策略(比如达到80%的时候,就来调oldGC)
4.GC算法(一般不要我们改)

1、GC调优原则:

并不是显著的提高系统性能,不是调了,性能就能提升几倍或者上十倍,JVM调优,主要调的是稳定
1、 大多数的java应用不需要GC调优
2、 大部分需要GC调优的的,不是参数问题,是代码问题
3、 在实际使用中,分析GC情况优化代码比优化GC参数要多得多;
4、 GC调优是最后的手段

2、GC调优目的:

GC的时间够小
GC的次数够少
发生Full GC的周期足够的长,时间合理,最好是不发生。
指标范围:
注:如果满足下面的指标,则一般不需要进行GC:
 Minor GC执行时间不到50ms;
 Minor GC执行不频繁,约10秒一次;
 Full GC执行时间不到1s;
 Full GC执行频率不算频繁,不低于10分钟1次;

3、特别说明:

多用户商城JVM堆内存配置建议不要低于1024M
JVM最大不超出服务器内存资源的80%

4、JVM性能场景分析案例

1、机器出现异常:java.lang.OutOfMemoryError: GC overhead limit exceeded
这个异常代表:GC为了释放很小的空间却耗费了太多的时间,
其原因一般有两个:1,堆太小,2,有死循环或大对象;

在这里插入图片描述

2、一个服务系统,经常出现卡顿,分析原因,发现Full GC时间太长:(Young GC一般30-60ms,oldGC小于1秒)
发现Young GC执行了54次,耗时2.047秒,每次Young GC耗时37ms,在正常范围,而Full GC执
行了5次,耗时6.946秒,每次平均1.389s,数据显示出来的问题是:Full GC耗时较长,分析该系
统的是指发现,NewRatio=9,也就是说,新生代和老生代大小之比为1:9,这就是问题的原因:
1,新生代太小,导致对象提前进入老年代,触发老年代发生Full GC; 2,老年代较大,进行Full GC时耗时较大;
优化的方法是调整NewRatio的值,调整到4,发现Full GC没有再发生,只有Young GC在执行。这
就是把对象控制在新生代就清理掉,没有进入老年代

在这里插入图片描述

5、JVM常见报错原因汇总:

1、年老代堆空间被占满异常: `java.lang.OutOfMemoryError: Java heap space`
 2、持久代被占满异常: `java.lang.OutOfMemoryError: PermGen space` ####说明: Perm空
间被占满
3、堆栈溢出 异常: `java.lang.StackOverflowError` ####说明:这个就不多说了,一般就是递
归没返回,或者循环调用造成
4、系统内存被占满异常: `java.lang.OutOfMemoryError: unable to create new native thread`
com.mysql.jdbc.util.ReadAheadInputStream.fill()

在这里插入图片描述

阅读 67
0 声望
0 粉丝
0 条评论
你知道吗?

0 声望
0 粉丝
宣传栏