服务高峰期gc,导致服务不可用

随着应用程序的复杂性和负载的不断增加,对JVM进行调优,也是保障系统稳定性的一个重要方向。

需要注意,调优并非首选方案,一般来说解决性能问题还是要从应用程序本身入手(业务日志,慢请求等),只有在必要时才对jvm进行调优(gc日志和监控异常)。

下面会提供一个线上案例,说明gc调优的重要性。

02_jvm性能调优_垃圾收集器的实现-CSDN博客

调优关注指标

吞吐量

程序运行过程中执行两种任务,执行业务代码的任务和执行垃圾回收的任务;

吞吐量计算公式:CPU在用户应用程序的运行时间/(CPU在用户应用程序的运行时间+CPU在垃圾回收程序的运行时间)

简单理解就是,吞吐量大,意味着应用程序运行的时间越多,执行业务的任务越多。

那么吞吐量多大合适呢,对于我们业务系统来说,肯定是越大越好了,但吞吐量太大会导致什么问题呢?

停顿时间

因为JVM在进行垃圾回收的时候,有些特有的阶段需要停止业务程序的运行,只有这样它才能准确的找到所有可达的节点,确定哪些是垃圾对象并进行清理。

例如:gc停顿100ms,意味着在这100ms内应用程序无法运行。注意这里的停顿时长,只是JVM停止业务程序执行垃圾回收任务的时长,并不是总的垃圾回收时间(有的收集器是一个回收阶段是有多个停顿的)

堆内存大小

当gc完成后,通常会释放一大块内存空间,所以如果频繁的gc,但可用内存没有下降的趋势(或趋势比较小),通常暗示有内存泄漏的问题。

以上三者的关系

这3个指标不可能同时达到,因为他们是一个不可能的关系。

内存变大,要回收的东西肯定变多,停顿时间肯定也会延长。

吞吐量增加,必然要减少垃圾回收的频率,频率降低,垃圾回收停顿的时间也会延长。

停顿时间减少,需要增加gc的频率,导致吞吐量下降。

因此,目前的调优方向主要是吞吐量和暂停时间。(我们的目标是停顿时间竟可能小的情况下,达到最大的吞吐量)

案例-停顿时间过高

系统配置2c12g,默认使用并行回收器。

通过下图的监控,可以发现,gc频率低,但停顿时间比较长(通常停顿时间尽量不要超过300ms)

因为行回收器会导致暂停时间变长,可以考虑更换垃圾收集器(G1) -XX:+UseG1GC -XX:MaxGCPauseMillis=300 ,通过设置合理的暂停时间,减低停顿时间。

为什么没有使用cms呢?

在 JDK 1.8 中,G1 垃圾收集器(Garbage-First Garbage Collector)被引入作为一种新的选择,旨在替代老旧的 CMS(Concurrent Mark Sweep)收集器。随着 Java 平台的发展,CMS 逐渐退出了舞台,原因主要包括以下几点:

1. **停止更新和维护**:
   自 JDK 9 开始,CMS 收集器就被标记为不推荐使用(deprecated),并在后续的版本中被彻底移除。Oracle 宣布不再对 CMS 收集器进行更新和维护,这意味着任何新的性能改进或者 bug 修复都不会应用于 CMS。

2. **并发模式失败**:
   CMS 收集器在处理大量并发数据时可能会遇到 "并发模式失败"(Concurrent Mode Failure)的问题。这种情况发生时,CMS 收集器无法在用户线程运行的同时完成垃圾回收,导致它不得不进行一次完全的垃圾回收(Full GC),这将暂停所有用户线程,影响应用程序的响应时间。

3. **内存碎片问题**:
   CMS 是基于标记-清除算法的,这意味着它在回收内存时不会进行压缩,从而可能导致内存碎片。内存碎片会随着应用程序的运行逐渐累积,最终可能导致需要更大的连续内存空间时无法找到足够的空间,进而触发 Full GC。

4. **G1 收集器的优势**:
   G1 收集器被设计为一种服务器端的垃圾收集器,适用于多核处理器和大内存的机器。它具有以下优点:
   - **预测性停顿时间模型**:G1 收集器可以设置期望的停顿时间目标(Pause Time Goal),并尽可能地在这个时间内完成垃圾回收,从而提供更可控的停顿时间。
   - **并行和并发回收**:G1 能够充分利用多核处理器,同时在并发阶段减少应用程序的停顿时间。
   - **分区堆**:G1 将堆内存分割成多个区域(Region),这样可以更高效地进行垃圾回收,尤其是在处理大堆时。
   - **增量式清理**:G1 收集器可以逐步清理堆内存,而不需要一次性清理全部空间,这有助于避免长时间的停顿。
   - **压缩空间**:G1 在回收过程中可以进行空间压缩,从而减少内存碎片问题。

5. **社区和官方的推动**:
   Oracle 和 Java 社区推动使用更现代的垃圾收集器,如 G1 和后来的 ZGC(Z Garbage Collector)以及 Shenandoah,这些收集器旨在提供更低的停顿时间和更好的性能,特别是在大内存和多核心的环境中。

由于上述原因,G1 收集器成为了 JDK 9 及以后版本的默认垃圾收集器,并且随着 Java 平台的发展,G1 和其他新的垃圾收集器(如 ZGC 和 Shenandoah)继续得到改进,以满足现代应用程序对性能和响应时间的要求。

  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值