大水怪

一只专注技术的水怪

0%

JDK21适用指南

当前升级JDK的动力实际上主要来自三项:ZGC、虚拟线程、衍生生态

1.总体分析

一下对JDK高版本主要特性做一个总览分析

ZGC

优点:ZGC基本消除了GC带来的延迟,并且对大对象有更好的处理

不足:ZGC吞吐量比不上G1,即便分代ZGC吞吐量有了很大提升,但与G1依然有一定差距。

虚拟线程

优点:适用IO密集型应用,一方面可以提高系统性能,另一方面可以极大消除线程带来的内存压力

不足:在目前JDK21的版本中,虚拟线程存在的坑还比较多,个人不建议在可靠性要求较高的应用上使用

衍生生态

许多Java生态的框架都基于高版本jdk开发,并不再维护低JDK版本。如果想要探索基于高版本的框架,那么升级JDK也是势在必行的了。

2.什么应用适合升级JDK?

目标 适用应用 具体版本 风险
ZGC
  1. GC延迟敏感 的应用,例如缓存应用等
  2. 本地有 大缓存 频繁生成大对象 的应用
如果对吞吐量追求不高,可以考虑JDK17以上;
如果对吞吐量有较高要求,需要升级JDK21,并且开启分代特性。
分代ZGC并没有完全成熟,经过充分的验证后才可上线
虚拟线程 IO密集型应用 都可以升级(文件IO除外) JDK21
衍生生态 需要按照自己实际的调研进行升级考虑,例如S pring Modulith等 —— ——

3. 实际收益

分代ZGC

我们对一个缓存型服务升级了JDK21,并使用了分代ZGC,在没有明显观察到资源占用提高的前提下解决了GC带来的长尾问题。

我们在3.28下午发布了一个集群,这是这个集群发布前后的长尾响应耗时情况

这是与JDK11 G1集群的对比,黄线是JDK11+G1,绿线是JDK21+ZGC

另外也可以参考Netflix这篇很好的文章 https://netflixtechblog.com/bending-pause-times-to-your-will-with-generational-zgc-256629c9386b

虚拟线程

我们在一个 IO 密集型服务进行了全面jdk21升级,并进行了虚拟线程灰度验证。

下图验证时对比非虚拟线程,平台线程数从2000降低到300+(7.19-7.26期间是由于某个依赖组件不支持虚拟线程,某个依赖组件里面开了300个平台线程,7.26后某个依赖组件替换为虚拟线程池)

对于虚拟线程,我们单独开了一个集群用于灰度(下图vt 集群)

下图中黄色线是JDK21集群,绿色为JDK21+虚拟线程集群

非虚拟线程(jdk21) p95 虚拟线程(jdk21) p95 降幅
列表查询 284 239 19%
详情查询 589 493 16.3%

加上升级jdk21本身带来的优化,对比jdk11的应用,虚拟线程+jdk21带来的p95降幅大概在20%

TODO:

使用虚拟线程后,不再需要像传统线程池一样进行参数调整,例如线程数,队列大小等等。

以前使用的线程池似乎会在某些场景下存在任务积压的问题,导致耗时大面积上升,切换后我们会进行压测,预期能将单机流量提升3倍以上。