JDK8升级到JDK17记录

JDK升级的需求背景,以及升级过程中遇到的问题

背景

某个项目属于基础服务,平时qps很高,扩容前共7个实例(8c8g),单机最高约8kqps。扩容后16个实例(6g12g),单机最高大约3k+qps,总qps高峰约4w qps。(使用了一致性hash做负载均衡+内存缓存,所以各个单机负载有一些差距)

关键接口tp9999平均到150ms左右,业务方需求压缩到80ms左右。经过分析和改造,主要的tp9999耗时被卡在了parnew gc的stw上。尝试对CMS+ParNew做了各种参数调优,也尝试了g1做gc,发现tp9999也很难压缩到100ms内。

ZGC是一款基于Region内存布局的、不分代的设计,使用了读屏障、染色指针和内存多重映射等技术实现可并发标记-整理算法,旨在实现以下几个目标:

  • 停顿时间不超过10ms(不管现在操作的内存有多么的庞大,都维持在10ms以内的收集)
  • 停顿时间不随heap(堆内存)大小或存活对象大小增大而增大(垃圾随便多,停顿时间都在10ms内)
  • 可以处理从兆(M)到几T大小的内存空间(完全符合当前以及未来的硬件发展水平)

zgc是一款可伸缩、低时延、并发垃圾收集器,对8MB到16TB的堆大小,都能达到毫秒升至亚毫秒级别的gc,公司内部也有类似需要超低时延的项目,他们升级了zgc,并且tp9999下降效果明显,所以决定尝试升级zgc。zgc在jdk 15正式转正,而jdk17是之后的第一个LTS,所以升级jdk8到jdk17,改用zgc。

CMS+ParNew存在的问题

虽然没有什么老年代gc,但是年轻代parnew的回收效果并不理想,年轻代的gc停顿时间特别长,大约在90ms-150ms左右,主要耗时在暂停线程进入safepoint。 gc_log

踩坑

  • jdk8升级到jdk17,中间有一些jar不兼容的地方,需要处理升级。

  • zgc使用了内存多重映射,将同一块物理内存映射为Marked0、Marked1 和 Remapped 三个虚拟内存。而在Linux/x86-64平台上的ZGC使用了多重映射将多个不同的虚拟内存地址映射到同一个物理内存地址上,多对一映射。意味着ZGC在虚拟内存空间看到的地址空间比实际的堆内存容量更加大。容器内容易因为被误认使用内存突破limits被重启进程。

  • Garbage Collection (High Usage):因为zgc看起来使用的内存大小比实际使用的内存要大得多,所以一开始分配的堆内存大小很小,只分配了2700M,出现了很多的High Usage和Allocation Stall的GC,调整了堆内存后不再出现。

  • Garbage Collection (Allocation Stall):晚高峰时,会出现一段时间Allocation Stall,并且出现因为内存分配空间不足,线程等待的现象。调整了-XX:ZCollectionInterval,设置到30s(每30s一次定时gc)。 Allocation_Stall

总结

zgc网上相关资料比较少,且大幅度升级JDK版本,容易存在风险。但是在追求低时延的场景下,zgc确实显著降低了tp9999的耗时。

  • cms_tp9999 cms_tp9999
  • zgc_tp9999 https://raw.githubusercontent.com/RussXia/RussXia.github.io/master/_pic/zgc_tp9999.png

另外,zgc公司内部很多监控目前还并不支持,还需要公司内部的监控组件的升级,gceasy支持zgc日志的解析。

升级

jaxb和javax.annotation依赖

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-core</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>javax.activation</groupId>
  <artifactId>activation</artifactId>
  <version>1.1.1</version>
</dependency>

Zookeeper 3.4 does not support JDK 17 : because it's not resolvable

https://github.com/apache/kyuubi/issues/1941

参考

美团-新一代垃圾回收器ZGC的探索与实践

JVM ZGC

升级Java17问题记录

ZGC max heap size exceed physical memory