作者 | 郑波(岱泽)
来源 | 阿里开拓者公众年夜众号
业务平台升级JDK11,基于两个出发点:一、jdk8于2019年1月停滞掩护,springboot2.1之后的版本已经兼容JDK11,springboot3.0完备放弃对JDK8的支持,未来属于更高版本的JDK;二、在试点国产化芯片的过程中,由于JDK8对Arm架构的优化不敷,导致国产化芯片无法发挥自身的性能上风,为了更好的适配国产化,务必要求对JDK版本进行升级。基于上述两个出发点,业务平台于21年12月启动了对JDK版本升级的适配之路。这里回顾全体升级过程,对升级过程中的问题做一下记录
一、升级版本的选择
当时有两个JDK版本可供选择,JDK11、JDK17,从长远开来,JDK17更代表未来,但由于JDK11 比较JDK17的变革并不大,比较之下从JDK11升级到JDK17的寻衅要相对小。由于升级的基本都是电商核心系统,基于风险的掌握,从JDK8升级到JDK11,随后再从JDK11升级到JDK17是一个更合理的选择。
二、GC选择及功能适配
业务平台核心系统利用了非常多的定制化功能,比如GCIH、CMS GC、异步日志、Wisp、Jwarmup、UncommonNullCast、多租户,为了减少对业务的影响,同时保障JDK11比较JDK8不会产生性能的退化,干系的特性均须要在JDK11上进行适配。同时为了避免GC算法的调度对业务运维及稳定性的影响,升级初期决定依旧利用CMS GC,仅灰度少量的G1
特性
特性解释
GCIH
营销利用GCIH缓存营销数据,大匆匆强依赖的特性
CMS GC
核心业务利用的GC算法,为了避免对业务利用上的影响,须要保留Cms GC的支持
异步GC日志
GC日志异步化,降落业务的影响
Wisp
协程支持,buy2、carts2上均在利用,对业务的性能3-5%的性能优化
JWarmup
启动预热,核心系统利用该功能降落启动过程中C1、C2带来的CPU飙升,业务抖动问题
UncommonNullCast
-XX:CompileCommand=
退优化干系的优化参数,避免部分场景下退优化带来的性能问题
-Dcom.alibaba.jdk.verifyECDSATrailing
跳过ECDSA尾部零校验,兼容老的ECDSA数据,Tp3和支付宝交互中,须要依赖
三、升级JDK11干系组件的升级
在升级JDK11的过程中,业务代码的改造只是个中之一,还涉及到业务依赖的各种组件之间的升级适配,包括Pandora、Tomcat、星环容器、天启、Doom、天擎等测试工具的升级支持
组件
升级改造点
Tomcat
非Pandoraboot的运用,强依赖Tomcat,目前大部分业务利用的依旧是Tomcat7,但Tomcat7 本身对JDK11的支持存在问题(ECJ的版本过低,在存在动态编译代码的情形下,比如:jsp、模板预演、groovy等,由于不识别jdk11,将目标代码编译成低版本的代码,导致性能及功能受损)。由于tomcat7 和tomcat8对jar包加载的顺序有了调度,导致升级到tomcat8本钱会相对较高,为了降落改造本钱,对tomcat7进行改造。(https://bz.apache.org/bugzilla/show_bug.cgi?id=57129)
最新的版本: taobao-tomcat-7.0.108.ecj
Pandora
Pandora各组件对JDK11的版本支持,在项目启动之初,Pandora已经在对JDK11进行了适配,但在实际升级利用中,依旧发生了一些不兼容的问题,期间紧张有
做事端利用JDK11版本运行,客户端利用JDK8的场景下,做事端抛的非常经由Hession序列化后,无法在JDK8上进行反序列化的情形。该问题前期评估,紧张是客户端感知的缺点发生变革,风险可控,实际在上线过程中,消费者侧的感知发生变革。最新的版本: 2022-07-stable
天启
天启作为业务平台最核心的测试用力回归工具,在全体适配开始之初,就作为高优先级适配,天启内部利用了很多序列化及记录Record的过程,本身为了做代码增强,利用了相对较多的hack的办法,因此这部分改造及适配本钱最大,适配过程中,一方面须要调度doom的依赖,其余一方面须要保障测试用力能正常回归
天擎
天擎作为业务平台预发环境隔离的工具,预发回归测试均须要进行依赖。这部分的改造也须要提提高行适配。
四、灰度及上线流程的选择
业务平台核心运用很多都是伴随taobao业务发展起来的运用,具有历史代码多、依赖组件广的特点,核心系统中存在非常多的二三方包依赖,在升级之初考虑利用JDK供应的兼容性扫描工具进行剖析,但在实操过程中,扫描到的不兼容代码过多,但实际上大部分并没有利用到的情形。如果按照扫描出来的结果推动干系二三方包的适配,全体工程量是完备无法评估的,全体升级节奏也无法把控。为理解决该问题,我们决定整体的升级节奏调度并不追求完备的代码兼容。只对实际影响业务运行的代码做兼容处理。由于整体的升级节奏也就变成了如下几步
1) 代码利用JDK8进行编译,但哀求代码可以同时在JDK8及JDK11上运行2) 上线过程中,先将日常及预发环境的版本切换成JDK11和JDK8同时运行,回归测试过程中同时测试JDK11、JDK8版本下的运行情形3) 线上逐步灰度JDK11运行环境的功能,做好监控及线上排查定位。随着几次大匆匆下来后,逐步将所有的容器切换到JDK11,下线JDK8环境的容器。4) 利用运行态的JDK11特性,优化系统性能5) 将编译从JDK8切换到JDK11 ,同时充分JDK11本身的新的特性。基于上述的升级步骤,对业务代码的升级改造也做了调度,业务在利用过程中,同时安装JDK8和JDK11,业务利用脚本的办法掌握线上的JDK11及JDK8的灰度比例。同时经由多轮大匆匆: 38大匆匆灰度10台容器、日常灰度100台、618灰度一个单元、99大匆匆灰度所有机房if [ -f /home/admin/logs/jdk11.enable ]; then export JAVA_HOME=/opt/taobao/install/ajdk11_11.0.14.13/ export JDK11_ENABLE=true echo "enable jdk11 , use new JAVA_HOME : ${JAVA_HOME}"fiif [ "$JDK11_ENABLE" == "true" ]; then CATALINA_OPTS="${CATALINA_OPTS} -Xlog:gc:${MIDDLEWARE_LOGS}/gc.log:time" CATALINA_OPTS="${CATALINA_OPTS} --add-exports=java.base/jdk.internal.loader=ALL-UNNAMED --add-exports=java.base/jdk.internal.loader=jdk.unsupported --patch-module jdk.unsupported=/home/admin/buy2/bin/java9-migration-helper-0.1.jar" CATALINA_OPTS="${CATALINA_OPTS} -Dio.netty.tryReflectionSetAccessible=true --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED" CATALINA_OPTS="${CATALINA_OPTS} --add-exports=java.base/jdk.internal.util.jar=ALL-UNNAMED --add-exports=java.base/jdk.internal.util.jar=jdk.unsupported" CATALINA_OPTS="${CATALINA_OPTS} --add-opens=java.base/com.alibaba.wisp.engine=ALL-UNNAMED" CATALINA_OPTS="${CATALINA_OPTS} -XX:CompileCommand=stableif,::" test -z "$JPDA_ADDRESS" && export JPDA_ADDRESS=:8000 #gson兼容 CATALINA_OPTS="${CATALINA_OPTS} -Djava.locale.providers=COMPAT,SPI"else CATALINA_OPTS="${CATALINA_OPTS} -Xloggc:${MIDDLEWARE_LOGS}/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps" CATALINA_OPTS="${CATALINA_OPTS} -XX:-UncommonNullCast -XX:CompileCommand=stableif,::" test -z "$JPDA_ADDRESS" && export JPDA_ADDRESS=8000fi
JDK11比较JDK8之间的关键的变革
参考:Oracle JDK Migration Guide
● 版本号格式的变革
● 本地化的优先级变革
● module化
● 废弃代码清理
● JDK日志架构变革
由于业务代码中旧的代码量较多,为了减少全体升级的繁芜度,整体的升级策略,以兼容旧的代码逻辑为主,尽可能的升级到新的版本中(并不是利用jdk11的最佳实践进行直接升级)。
在实际的适配过程中,创造紧张的兼容问题集中在版本号格式的变革带来的不兼容。对付这部分代码逻辑紧张哀求干系业务进行改进即可,对付一些无法找到掩护者的二方包来说,直接通过反编译的办法进行整体改造。
二方包
兼容版本
改造缘故原由
citrus-webx-all-in-one
3.2.4.1-jdk11
JDK11版本号格式变革,导致无法启动,由于目前已经无法找到对应掩护者,针对这部分二方包,反编译后提交仓库供业务利用。
toolkit-webx-all-in-one
2.0.3-jdk11
toolkit.common.lang
com.alibaba.toolkit:toolkit-common-lang:jar
1.0-jdk11
citrus-webx-all-in-one
3.2.4.1-jdk11
forest-store
8.1.11
利用了非公开的类,在升级到jdk11后,干系的类发生了变革,须要做相应的改造升级
ip-client
5.5.69
sic-client
1.5.33
com.alibaba.ultron:common-sdk-datasource:1.0.0-buy2.0-4
1.0.0-jdk11-beta.2
common-uic-common
3.8.8-jdk11 +
com.cainiao.cdc:cdc-client
com.cainiao.cdc:cdc-common
1.13.25
利用了unsafe的包,导致在升级到JDK11后,干系的类无法利用
gson
2.8.9
由于JDK11确当地化变革,导致gson在解析韶光格式上存在不兼容的情形,升级gson版本,同时在启动时添加 -Djava.locale.providers=COMPAT,CLDR 参数。https://github.com/google/gson/pull/1211
点击查看原文,获取更多福利!
https://developer.aliyun.com/article/1162353?utm_content=g_1000368533
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开拓者社区不拥有其著作权,亦不承担相应法律任务。详细规则请查看《阿里云开拓者社区用户做事协议》和《阿里云开拓者社区知识产权保护指引》。如果您创造本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将急速删除涉嫌侵权内容。