🌹🌹 如果您觉得我的文章对您有帮助的话,记得在 GitHub 上 star 一波哈 🌹🌹
0 背景
酷划商业平台容器化之后,应用的启动性能下降明显。经常出现 10 秒以上的接口响应延迟。分析了应用启动时的性能指标,发现 CPU 负载和使用率同时飙升(甚至打满),后来发现是 C2 编译器占用大量 CPU 时间片。遂决定优化之。
已经做的优化:
- 调整多个 pod 的启动顺序:并行 -> 串行
- 调整 JIT 编译线程数
初步优化后,将延迟降低到了 5 秒左右。
然后考虑,能不能将每次 JIT 编译的结果缓存下来,下次应用启动的时候直接使用,减少应用启动初期解释执行和收集 profile 带来的性能影响。
调研发现,目前已有的实现方案有以下几种:
- Oracle Java9 以后的 AOT(配合 Graal 编译器使用)
- 阿里 JDK-Dragonwell8(基于 JDK8,利用其 JWarmup 缓存 JIT 编译结果)
- Azul Zing VM 的 ReadyNow
- IBM J9 的 AOT
最终决定对前两种进行试验。
PS:本文只讨论 OracleJDK 的升级过程
1 升级 Java11 的目的
- 利用 AOT 解决应用冷启动的性能问题
- 新特性 http2 的使用
- 容器相关的新特性的使用
2 初期遇到的问题
直接安装 Oracle JDK11,将 IDE 的环境切换到 JDK11 后,就开始各种报错。例如:
注解 PostConstruct 找不到了。这个问题是 Java11 中移除了 javax 包引起的。
然后开始翻官方文档,有一篇专门针对从 JDK8 升级到后面新版本的。
传送门:Migrating From JDK 8 to Later JDK Releases
这里面,主要关注哪些会导致应用编译失败或无法启动的更改。
主要有以下这些 API 移除:
- 移除 java.* APIs 和 javax.* APIs
- 移除 com.sun.*
- 移除某些 jdk.*
- java.awt.peer Not Accessible
- Removed com.sun.image.codec.jpeg Package
另外下面的 GC 参数组合已失效,如果配置会导致启动报错:
- DefNew + CMS
- ParNew + SerialOld
- Incremental CMS
由于移除了永久代,以下相关配置会导致一些警告:
- -XX:MaxPermSize=size
- -XX:PermSize=size
告警信息如下:
Java HotSpot(TM) 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
更详细的信息请参考官方文档的内容。
2.1 解决上面遇到的问题
上文中,切换到 JDK11 后,javax.annotation.PostConstruct 被移除了。我们可以手动将 javax.annotation 的 jar 包引入,即可解决。
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
其他的问题按照同样的思路解决即可。
3 远程 debug 问题
Java9 以后的版本,JPDA 的 address 配置格式发生了一些变化。
Java8 及以前,用如下形式:
-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
Java9 及以后,改为下面这样,否则无法链接到远程端口:
# 区别在于address,要变成 *:PORT 格式
-Xdebug -Xrunjdwp:transport=dt_socket,address=*:8000,server=y,suspend=n
原因:
可参考 StackOverflow 的一个 issue:What are Java command line options to set to allow JVM to be remotely debugged?
大概是说,Java9 及以后的版本默认只支持本地连接到 debug,即 address=8000,这个格式默认解析出来的 IP 是 localhost,改成 address=*:8000 后,可匹配任何 IP。
延伸:
Java5 之前,使用-Xdebug 和-Xrunjdwp 来告知 jvm 运行在 debug 模式下,这个方式在以后的版本中仍然适用,但在此模式下运行的 JVM,只会在解释执行的模式下运行,不会有 JIT 的参与,所以运行较慢,因此生产环境一定不要开启这个参数。
后续...
采坑仍在继续,会在 GitHub 上持续更新。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于