找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3412

积分

0

好友

464

主题
发表于 4 天前 | 查看: 19| 回复: 0

垃圾回收器的暂停问题,对于那些对实时响应有严苛要求的服务来说,一直是个令人头疼的难题。像 CMS 和 G1 这类主流回收器,动辄数十甚至上百毫秒的停顿时间,在高敏感场景下堪称致命。更不用说,针对它们的调优本身门槛就不低,需要对内部机制有相当了解才能奏效。不过,随着 ZGC(Z Garbage Collector)的出现,这个痛点迎来了转机。ZGC 最初在 JDK 11 中作为实验性功能亮相,在 JDK 15 中宣布生产就绪。考虑到 JDK 17 才是第一个真正面向大众的长期支持(LTS)版本,并且已有不少公司开始采用,本文将重点围绕 JDK 17 展开。

ZGC 作为一款设计目标明确的低延迟垃圾收集器,旨在满足以下几个核心指标:

  • 支持 8MB 到 16TB 的堆内存大小。
  • 保证最大 GC 暂停时间不超过 10 毫秒。
  • 在最坏情况下,吞吐量降低不超过 15%(根据实测,如果参数配置不当,可能影响更大。可以理解为这是一种用额外的 CPU 资源来换取极致 GC 暂停时间的权衡策略)。

核心优势:无法拒绝的低延迟

毫秒级 GC 暂停,满足极致低延迟业务需求

根据美团技术团队分享的数据,在 Zeus 服务的不同集群中,启用 ZGC 为低延迟(TP999 < 200ms)场景带来了显著收益:

  • TP999:下降了 12~142ms,降幅达 18%~74%。
  • TP99:下降了 5~28ms,降幅达 10%~47%。

这种级别的 GC 停顿改善,是使用 CMS、Parallel GC 或 G1 等传统回收器时,无论如何精细调优都难以企及的。它能确保应用在 JVM 层面的卡顿被控制在 1 毫秒以内,这正是升级 JDK 17 并启用 ZGC 最具说服力的理由。

当然,除了低延迟,升级 JDK 17 还有一些额外的“甜点”:

  • 生态演进:新版 Spring Boot 官方已将最低支持版本设为 JDK 17,想使用最新的 Spring 特性,升级是必经之路。
  • 性能与安全:JIT 编译器得到增强,同时包含 Sealed 类、模式匹配、Records 等新语言特性。升级也能获得更好的安全性,包括已修复的漏洞和强化的安全机制。

适用场景建议

  • 推荐场景:网关服务、Web API 等对响应延迟敏感的服务。
  • 暂不推荐:CPU 密集型的定时任务、批量处理任务。

升级前后性能对比

让我们直接看数据,这是最直观的。

测试环境:

CPU: 4c
Mem: 6GB

G1 GC 参数配置:

    -Xmx3500m -Xms3500m -XX:+UseG1GC -XX:MaxGCPauseMillis=100
    -XX:G1ReservePercent=10 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=5
    -XX:G1HeapRegionSize=16m -XX:MaxTenuringThreshold=14
    -XX:SurvivorRatio=8

ZGC 参数配置:

--add-opens=java.base/java.lang=ALL-UNNAMED -Xms3500m -Xmx3500m -XX:ReservedCodeCacheSize=256m -XX:InitialCodeCacheSize=256m -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ConcGCThreads=1 -XX:ParallelGCThreads=3 -XX:ZCollectionInterval=60 -XX:ZAllocationSpikeTolerance=4 -XX:+UnlockDiagnosticVMOptions -XX:-ZProactive  -Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/opt/gc-%t.log:time,tid,tags:filecount=5,filesize=50m

上述两套参数均已在生产环境验证,对应的机器单机业务 TPS 约为 1500。

GC 耗时对比

G1 GC与ZGC暂停耗时对比折线图

从上图可以清晰地看到,GC 耗时有着质的飞跃。G1 GC 的暂停在数十毫秒级别波动,而 ZGC 的停顿被稳定地压制在 1 毫秒左右。这种差距是传统垃圾回收器难以通过调优达到的,它从根本上降低了JVM垃圾回收对服务响应时间的影响。

CPU 使用率对比

容器CPU使用率对比折线图

在 CPU 使用率方面,运行相同的业务代码,使用 JDK 17 与 ZGC 的组合,会比 JDK 8 搭配旧回收器高出约 10% ~ 20%。这印证了前面提到的“以CPU换时间”的策略,ZGC 通过更频繁地利用并发线程进行垃圾回收工作,来换取极致的低停顿。这对于追求低延迟的后端服务架构来说,通常是值得的投入。

升级与配置实践

1. JDK 17 安装

首先需要在目标环境安装 JDK 17。以下提供几种常见方式的示例:

# Ubuntu / Debian 系统安装
sudo apt install openjdk-17-jdk

# Docker 基础镜像选择
docker pull openjdk:17-slim
docker pull openjdk:17-jdk-oraclelinux7

# Dockerfile 示例
FROM openjdk:17-slim

2. JVM 参数调整

安装好 JDK 17 后,下一步就是配置 JVM 参数以启用和优化 ZGC。下面是一组经过生产环境验证的参考参数,你可以根据实际情况调整换行格式:

    --add-opens=java.base/java.lang=ALL-UNNAMED \
    -Xms1500m -Xmx1500m \
    -XX:ReservedCodeCacheSize=256m \
    -XX:InitialCodeCacheSize=256m \
    -XX:+UnlockExperimentalVMOptions \
    -XX:+UseZGC \
    -XX:ConcGCThreads=1 -XX:ParallelGCThreads=2 \
    -XX:ZCollectionInterval=30 -XX:ZAllocationSpikeTolerance=5 \
    -XX:+UnlockDiagnosticVMOptions -XX:-ZProactive \
    -Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/opt/gc-%t.log:time,tid,tags:filecount=5,filesize=50m \
    -XX:+HeapDumpOnOutOfMemoryError \
    -XX:HeapDumpPath=/opt/errorDump.hprof

关键参数释义

为了方便理解,下表对上述部分关键 JVM 参数进行了说明:

JVM ZGC关键参数配置说明表

总而言之,对于响应延迟要求极高的现代Java服务,从 JDK 8 升级至 JDK 17 并启用 ZGC,是一项能带来显著收益的技术决策。它并非简单的版本更新,而是通过新一代垃圾回收器的能力,从根本上优化了应用的响应确定性。当然,任何升级都需要经过充分的测试,建议在预发或小流量环境中验证后再全量推广。如果你想了解更多关于 JVM 调优或微服务架构的实践,可以到 云栈社区 与更多开发者交流探讨。




上一篇:如何用 ASCII 草图与 AI 协作,快速构建后台 Dashboard 前端?
下一篇:Spring Boot与Spring Cloud Alibaba:构建企业级微服务与DDD架构模板解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 10:26 , Processed in 0.633316 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表