随着springboot3的正式版推出,最小可用的jdk版本为17。最大的亮点是颠覆性的zgc,可以将stw时间控制在亚毫秒级别,接着jdk21推出了分代zgc。根据jdk官方说法,此gc算法适用于任何内存条件下,多核cpu环境。我们也在各个环境的生产系统做到了验证(2c4g、4c8g、8c16g)。对于中间件,rocketmq、kafka、es、nacos等。因所用jdk版本尚未完全支持,且目前也没有遇到过问题,暂未做升级。
对于新项目来说,springboot3+jdk21已经可用,基本上不会有问题。
对于springboot2+jdk8项目的升级,也相对较简单。
升级步骤
1、jdk我们选择zulu21 https://www.azul.com/downloads/#zulu
2、pom配置统一到21
|
|
3、从2.7.x升级springboot到最新版本,根据官方的Migration Guide升级即可 https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide
4、循环依赖,某些项目目前碰到了此类情况。修改配置即可
|
|
5、lombok版本升级到最新
6、找不到相关的类,一般是因为从jdk11开始删除了j2ee相关的类。根据报错引入jakarta相关包即可,代码中将j2ee相关代码,改为使用jakarta
7、某些应用,会使用到反射。新jdk版本中因为安全问题,做了一些限制。目前做得比较粗暴,在jvm中增加如下配置
|
|
8、swagger改为使用springdoc-openapi 依赖,并做相应的代码修改
9、docker打包基础镜像修改为统一使用zulu21
升级后,所有生产环境jvm配置统一修改
以下是用得最多的4c8g配置
|
|
因为目前公司的java服务均跑在容器内部,Huge Pages、NUMA Support等未做开启
总结
本文探讨了如何升级到jdk21,并使用最新的分代zgc。jdk21也带来了很多简便的新语法和适合IO密集的虚拟线程。虚拟线程相比于平台线程在某些场景下优势明显。只是需要注意仅使用可重入锁对象,而不使用synchronize关键字(反而降低性能)。相关资料:https://openjdk.org/jeps/444
经过实践和测试,我们发现升级后的系统在垃圾回收方面表现出色,暂停时间确实如官方所说被控制到了亚毫秒内。尽管这个优化会额外消耗cpu资源,但获得了超低stw时间,权衡这下显然非常值得。
相比其他已经经过生产环境调优的垃圾回收器(G1、Parallel、CMS),ZGC的性能和稳定性都非常优秀,几乎不需要太多额外的调优,就可以得到响应时间的降低和吞吐量的增加。即使在以前吞吐量有优势的Parallel,依然具有优势。
ZGC可以统一江湖了!另据得到的消息,某些大厂主要服务均升级到了jdk21。但也进一步说明了,(分代)zgc和虚拟线程的强大。你们还在用jdk8吗?
更新
新增一些中大厂使用jdk17/jdk21和zgc的案例,作为以后项目的参考
References
Spring-Boot-3.0-Migration-Guide:迁移到springboot3
转转:“分代ZGC在转转商列服务中的实践”
得物:“亚毫秒GC暂停到底有多香?JDK17+ZGC初体验|得物技术”
京东:“JDK11升级JDK17最全实践干货来了”
京东营销:“JDK 17 营销初体验 —— 亚毫秒停顿 ZGC 落地实践”
美团: “新一代垃圾回收器ZGC的探索与实践”
阿里云:“The Past and Present of JDK8 and JDK17 to the Future of JDK21”
Automq:Java ZGC 深度剖析及其在构建低延迟流系统中的实践心得